How can I create wiggle animation (damped oscillations)? - sdk

I'm new to programming and making an app for ipad with Corona SDK.
I want to take a wiggle animation like this:
http://www.youtube.com/watch?v=kXxQU0T7I2A#t=0m40s (t=40-44sec).
How can I do that? What way is easier: use physics with specific joints or use transitions?
Maybe some examples?

The solution of a damped harmonic oscillator is pretty simple:
startAmplitude*sin(omega*t+startPhase)*exp(-t*dampningConstant)
I'd use this to describe the angle of the joint. From angle and length of arm you can calculate an (x,y) pair. If you have several parts in a series you can simply add the x and y values of the different steps.
This doesn't describe the physics of a coupled system of joints correctly, but might be good enough for what you need.

To simulate a damped spring you need to specify:
The damping force (0=no damping, 1=full damping)
The spring constant (0=no spring, increasing values results in a stronger spring)
Each frame, you want to keep track of the velocity of the object, and:
Damp (slow) the velocity of the object
Modify the velocity by adding a force pulling it back to rest
Adjust the position of the object based on its velocity
In pseudo-code, this is:
velocity = velocity * (1-dampingFactor) + deviationFromRest * springConstant
position = position + velocity
You can interactively play with this on my website:
http://phrogz.net/damped-spring-oscillations-in-javascript

Related

How is the initial velocity of UISpringTimingParameters specified?

I'm trying to perform a spring animation on a view which is released by the user's pan gesture and may have a non-zero velocity. I'm basically trying to recreate the animation of this WWDC video where they use UISpringTimingParameters(dampingRatio:initialVelocity:). However, the documentation seems to contradict itself:
velocity
The initial velocity and direction of the animation, specified as a unit vector.
[...]
For example, if the total animation distance is 200 points and the view’s initial velocity is 100 points per second, specify a vector with a magnitude of 0.5.
If 0.5 is an example value, then apparently it doesn't need to be a unit vector after all. And it's not possible to encode a velocity in a unit vector in the first place.
Not being able to rely on the documentation, I tried plugging in several different values, but nothing lead to even remotely satisfactory results.
How do I use this API?
Good question.
TL;DR: If you are trying to animate something to a position in 2D, you need to animated each coordinate separately, each with the respective x / y velocity.
If you combine them by taking the scalar projection of the velocity onto your offset, you get a weird artifact where assuming the context of flicking a view around the screen, where the target is the center of the screen, and you are flicking the view up the right side, since the animation is to return to center, and since the combined velocity is going away from the center, the animation can only assume that the subject is moving in a straight line away from the center, and it will jag out to the right, before animating back to the center.
https://github.com/chrisco314/SpringAnimationTest

XNA rotation over given vector

I'm newbie in XNA, so sorry about the simple question, but I can't find any solution.
I've got simple model (similar to flat cuboid), which I cannot change (model itself). I would like to create rotate animation. In this particular problem, my model is just a cover of piano. However, the axis over which I'm going to rotate is covered by cover's median. As a result, my model is rotating like a turbine, instead of opening and closing.
I would like to rotate my object over given "line". I found Matrix.CreateLookAt(currentPosition, dstPosition, Vector.Up); method, but still don't know how o combine rotation with such matrix.
Matrix.CreateLookAt is meant for use in a camera, not for manipulating models (although I'm sure some clever individuals who understand what sort of matrix it creates have done so).
What you are wanting to do is rotate your model around an arbitrary axis in space. It's not an animation (those are created in 3D modeling software, not the game), it's a transformation. Transformations are methods by which you can move, rotate and scale a model, and are obviously the crux of 3D game graphics.
For your problem, you want to rotate this flat piece around its edge, yes? To do this, you will combine translation and axis rotation.
First, you want to move the model so the edge you want to rotate around intersects with the origin. So, if the edge was a straight line in the Z direction, it would be perfectly aligned with the Z axis and intersecting 0,0,0. To do this you will need to know the dimensions of your model. Once you have those, create a Matrix:
Matrix originTranslation = Matrix.CreateTranslation(new Vector3(-modelWidth / 2f, 0, 0))
(This assumes a square model. Manipulate the Vector3 until the edge you want is intersecting the origin)
Now, we want to do the rotating. This depends on the angle of your edge. If your model is a square and thus the edge is straight forward in the Z direction, we can just rotate around Vector3.Forward. However, if your edge is angled (as I imagine a piano cover to be), you will have to determine the angle yourself and create a Unit Vector with that same angle. Now you will create another Matrix:
Matrix axisRotation = Matrix.CreateFromAxisAngle(myAxis, rotation)
where myAxis is the unit vector which represents the angle of the edge, and rotation is a float for the number of radians to rotate.
That last bit is the key to your 'animation'. What you are going to want to do is vary that float amount depending on how much time has passed to create an 'animation' of the piano cover opening over time. Of course you will want to clamp it at an upper value, or your cover will just keep rotating.
Now, in order to actually transform your cover model, you must multiply its world matrix by the two above matrices, in order.
pianoCover.World *= originTranslation * axisRotation;
then if you wish you can translate the cover back so that its center is at the origin (by multiplying by a Transform Matrix with the Vector3 values negative of what you first had them), and then subsequently translate your cover to wherever it needs to be in space using another Transform Matrix to that point.
So, note how matrices are used in 3D games. A matrix is created using the appropriate Matrix method in order to create qualities which you desire (translation, rotation around and axis, scale, etc). You make a matrix for each of these properties. Then you multiply them in a specific order (order matters in matrix multiplication) to transform your model as you wish. Often, as seen here, these transformations are intermediate in order to get the desired effect (we could not simply move the cover to where we wanted it then rotate it around its edge; we had to move the edge to the origin, rotate, move it back, etc).
Working with matrices in 3D is pretty tough. In fact, I may not have gotten all that right (I hope by now I know that well enough, but...). The more practice you get, the better you can judge how to perform tasks like this. I would recommend reading tutorials on the subject. Any tutorial that covers 3D in XNA will have this topic.
In closing, though, if you know 3D Modeling software well enough, I would probably suggest you just make an actual animation of a piano and cover opening and closing and use that animated model in your game, instead of using models for both the piano and cover and trying to keep them together.

Mapping device tilt to player character (etc) movement behaviour

The context is an iPad game in which I want an on-screen object to be controlled by X/Y tilt of the device.
I was wondering if anybody can point me in the direction of resources for deciding on an appropriate mapping of tilt to the movement behaviour (e.g. whether people tend to use the "raw" rotation values to control the acceleration, velocity or direct position, and how comfortable players have been found to be with these different types of 'mapping' of device rotation to object movement).
I appreciate that the appropriate choice can depend on the particular type of game/object being controlled, and that some trial and error will be needed, but I wondered as a starting point at least what existing knowledge there was to draw on.
First you're going to want to apply a low-pass filter to isolate tilt from noise and your user's shaky hands, Apple shows this in their accelerometer examples
x = accel.x * alpha + x * (1.0 - alpha);
y = accel.y * alpha + y * (1.0 - alpha);
more alpha causes more responsiveness at the cost of more noisy input.
Unless your game is intentionally simulating a ball balancing on the face of the screen, you probably don't want to apply your tilt values to acceleration, but rather to target velocity or target position, applying "fake" smooth acceleration to get it there.
Also, this answer has a neat idea if Unity3d is acceptable for your project, and this paper has some handy numbers on the practical limits of using tilt control as input, including making the important point that users have a much easier time controlling absolute angle position than velocity of tilt.
So, we desire to move our character - we'll call him 'loco' - based on the accelerometer's x and y data.
Now, if we do want the magnitude of the tilt to affect the rate of loco's travel, we can simply factor the accelerometer x or y value directly into our algorithm for his movement.
For example: (psuedocode)
// we'll call our accelerometer value for x 'tiltX'
// tiltX is .5; // assume that accelerometer updated the latest x value to .5
// unitOfMovement = 1; // some arbitraty increment you choose for a unit of movement
loco.x += unitOfMovement * tiltValueX;
This will cause loco to move that number of pixels for each game cycle (or whatever cycle you are driving the updates for movement by) and that here is 1 pixel multiplied by the accelerometer value. So if the character normally moves 1 pixel right at full tiltX (1.0), then if tiltX comes in from the accelerometer at .5, loco will move half that. When the value of tiltX increases, so too will the movement of Loco.
Another consideration is whether you want the movement tied directly to the rate of accelerometer events? Probably not, so you can use an array to just hold the last ten x values (same concept for y values too) sent by the accelerometer and use the latest average of the array (sum of x values / number of elements in array) at each game loop. That way, the sensitivity will feel more appropriate than driving the movement by whatever the update rate of the accelerometer may be.
Have a look at Point in Tilt Direction - iPhone which is first answer is very helpful I think.

Easy code sample for formula for simulating deceleration of a rotating sphere due to friction and gravity?

I have a rotating sphere that the user rotates by applying a virtual force, like a virtual accelerator. I want to be able to simulate a nice momentum effect so that when they lift off the accelerator the ball winds down in speed in a natural and realistic way, as if due to friction and/or gravity. I don't want to get into any deep physics equations. I'd like to do this quick so if I could find a code sample that shows how to do this, or even a page of formulas clear enough that I could encode, that would be great.
I'd like a formula that has one or two adjustable coefficients that I could tune to make the ball decelerate faster or slower depending on my needs. I don't want to get into anything heavy like an open source physics library or the like. Just something simple.
I'm using Delphi 6 Pro but I also know C/C++, Basic, Java, and Javascript.
Velocity is change in displacement. Acceleration is change in velocity.
Gravity or friction just causes an acceleration (possibly negative).
So all you need to do is apply a negative acceleration when they do not activate the accelerator.
So lets assume you have an angle that is changing. Applying the accelerator increases the amount the angle changes by each iteration or time step. If your angle is t and your change in angle is called dt (angular velocity) then when the accelerator is applied you'll have:
t = t + dt
dt = dt + a
where a depends on how much force you're applying, or how much they've 'pressed' the accelerator (i.e. this is the acceleration).
You'll probably want to limit dt (i.e. speed of rotation) - if you only want to spin in one direction you'll have an upper positive limit and a lower limit of 0. If you want both directions, you can have a lower negative limit and an upper positive limit.
All you need to do is make a some negative number when the accelerator is not applied (if dt is positive - make a positive if dt is negative), and ensure you don't 'wrap' (i.e. make dt 0 when it gets near 0).
It has been some time ago, but according to my dynamics study books the Mass Moment of Inertia for a sphere is defined as I=(2/5)m*r^2. m is the mass, r is the radius of the sphere (all in SI untis). On this page you'll find some examples to use the mass moment of inertia to calculate deceleration of the sphere as a result of the applied negative torque. This toqrue is a result of the friction. Since you are not defining the material of the surface of the sphere and the surroudings you cannot calculate the friction and will have to choose a good force yourself.
As long as you are not solving stellar problems, I don't see how gravity has much to do with decelerating the rotation.
Friction is almost proportional to the current rotation speed (actually the speed on the surface of the sphere).
So a formula for the current rotation speed over time w(t) may be something like this:
w(t) = w0*exp(-c*(t - t0))
with t0 being the time the friction starts, wt being the rotation speed at that time.
The coefficient c > 0 determines how fast the speed will decrease - the higher c, the faster the speed will go down. This formula is valid for all t >= t0.
Note that for t = t0 the exp function returns 1 and you get the initial speed, while for t -> ∞ the exp function (and so the resulting speed) returns -> 0 (the minus in front of the c guarantees this).
You've already accepted an answer, but I'll put in my piece.
I'll assume you already know how to make the sphere spin at a constant rate, and how to make it accelerate under the applied torque. Making it decellerate is just a matter of applying another torque, one that must be calculated.
When an object slides on a solid surface, the rate of deceleration is constant. The force is in the direction opposite to motion, and its magnitude depends on a couple of things but not speed. When the object comes to a full stop, the force vanishes. The same applies to a globe turning on a solid pivot.
When an object passes through a fluid, the force of decelleration increases with speed, so the faster the object the greater the drag. As the object slows down, decelleration grows weaker, and the object keeps slowing down but never stops. This describes a globe spinning in air or water. At reasonably high speeds, drag is proporional to v2, and at very low speeds it is proportional to v (I don't know about the transition between these domains).
So I suggest t = -a wb, where w is angular velocity. The parameter a is the strength of the friction, and b describes the kind of decelleration; b=0 is like friction on a solid pivot, b=2 is like spinning in air, and b=1 is like rotating in syrup. Other values of b may or may not look realistic or be realistic.

2d trajectory planning of a spaceship with physics

I'm implementing a 2D game with ships in space.
In order to do it, I'm using LÖVE, which wraps Box2D with Lua. But I believe that my question can be answered by anyone with a greater understanding of physics than myself - so pseudo code is accepted as a response.
My problem is that I don't know how to move my spaceships properly on a 2D physics-enabled world. More concretely:
A ship of mass m is located at an initial position {x, y}. It has an initial velocity vector of {vx, vy} (can be {0,0}).
The objective is a point in {xo,yo}. The ship has to reach the objective having a velocity of {vxo, vyo} (or near it), following the shortest trajectory.
There's a function called update(dt) that is called frequently (i.e. 30 times per second). On this function, the ship can modify its position and trajectory, by applying "impulses" to itself. The magnitude of the impulses is binary: you can either apply it in a given direction, or not to apply it at all). In code, it looks like this:
function Ship:update(dt)
m = self:getMass()
x,y = self:getPosition()
vx,vy = self:getLinearVelocity()
xo,yo = self:getTargetPosition()
vxo,vyo = self:getTargetVelocity()
thrust = self:getThrust()
if(???)
angle = ???
self:applyImpulse(math.sin(angle)*thrust, math.cos(angle)*thrust))
end
end
The first ??? is there to indicate that in some occasions (I guess) it would be better to "not to impulse" and leave the ship "drift". The second ??? part consists on how to calculate the impulse angle on a given dt.
We are in space, so we can ignore things like air friction.
Although it would be very nice, I'm not looking for someone to code this for me; I put the code there so my problem is clearly understood.
What I need is an strategy - a way of attacking this. I know some basic physics, but I'm no expert. For example, does this problem have a name? That sort of thing.
Thanks a lot.
EDIT: Beta provided a valid strategy for this and Judge kindly implemented it directly in LÖVE, in the comments.
EDIT2: After more googling I also found openSteer. It's on C++, but it does what I pretended. It will probably be helpful to anyone reaching this question.
It's called motion planning, and it's not trivial.
Here's a simple way to get a non-optimal trajectory:
Stop. Apply thrust opposite to the direction of velocity until velocity is zero.
Calculate the last leg, which will be the opposite of the first, a steady thrust from a standing start that gets the ship to x0 and v0. The starting point will be at a distance of |v0|^2/(2*thrust) from x0.
Get to that starting point (and then make the last leg). Getting from one standing point to another is easy: thrust toward it until you're halfway there, then thrust backward until you stop.
If you want a quick and dirty approach to an optimal trajectory, you could use an iterative approach: Start with the non-optimal approach, above; that's just a time sequence of thrust angles. Now try doing little variations of that sequence, keeping a population of sequences that get close to the goal. reject the worst, experiment with the best -- if you're feeling bold you could make this a genetic algorithm -- and with luck it will start to round the corners.
If you want the exact answer, use the calculus of variations. I'll take a crack at that, and if I succeed I'll post the answer here.
EDIT: Here's the exact solution to a simpler problem.
Suppose instead of a thrust that we can point in any direction, we have four fixed thrusters pointing in the {+X, +Y, -X, -Y} directions. At any given time we will firing at most one of the +/-X and at most one of the +/-Y (there's no point in firing +x and -X at the same time). So now the X and Y problems are independent (they aren't in the original problem because thrust must be shared between X and Y). We must now solve the 1-D problem -- and apply it twice.
It turns out the best trajectory involves thrusting in one direction, then the other, and not going back to the first one again. (Coasting is useful only if the other axis's solution will take longer than yours so you have time to kill.) Solve the velocity problem first: suppose (WLOG) that your target velocity is greater than your initial velocity. To reach the target velocity you will need a period of thrust (+) of duration
T = (Vf - Vi)/a
(I'm using Vf: final velocity, Vi: initial velocity, a: magnitude of thrust.)
We notice that if that's all we do, the location won't come out right. The actual final location will be
X = (Vi + Vf)T/2
So we have to add a correction of
D = Xf - X = Xf -(Vi+Vf)T/2
Now to make the location come out right, we add a period of thrust in one direction before that, and an equal period in the opposite direction after. This will leave the final velocity undisturbed, but give us some displacement. If the duration of this first period (and the third) is t, then the displacement we get from it is
d = +/-(at^2 + atT)
The +/- depends on whether we thrust + then -, or - then +. Suppose it's +.
We solve the quadratic:
t = (-aT + sqrt(a^2 T^2 + 4 a D))/2a
And we're done.
In the absence of additional info, we can assume there are 3 forces acting upon the spaceship and eventually dictating its trajectory:
"impulses" : [user/program-controlled] force.
The user (or program) appear to have full control over this, i.e. it controls the direction of the impulse and its thrust (probably within a 0-to-max range)
some external force: call it gravity, whatever...
Such force could be driven by several sources but we're just interested in the resulting combined force: at a given time and space this external force acts upon the ship with a given strengh and direction. The user/program has no control over these.
inertia: this is related to the ship's current velocity and direction. This force generally causes the ship to continue in its current direction at its current speed. There may be other [space-age] parameters controlling the inertia but generally, it is proportional to both velocity and to the ship's mass (Intuitively, it will be easier to bring a ship to a stop if its current velocity is smaller and/or if its mass is smaller)
Apparently the user/program only controls (within limits) the first force.
It is unclear, from the question, whether the problem at hand is:
[Problem A] to write a program which discovers the dynamics of the system (and/or adapts to changes these dynamics).
or..
[Problem B] to suggest a model -a formula- which can be used to compute the combined force eventually applied to the ship: the "weighed" sum of the user-controlled impulse and the other two system/physics-driven forces.
The latter question, Problem B, is more readily and succinctly explained, so let's suggest the following model:
Constant Parameters:
ExternalForceX = strength of the external force in the X direction
ExternalForceY = id. Y direction
MassOfShip = coeficient controlling
Variable Parameters:
ImpulseAngle = direction of impulse
ImpulseThrust = force of thrust
Formula:
Vx[new] = (cos(ImpulseAngle) * ImpulseThrust) + ExternalForceX + (MassOfShip * Vx[current])
Vy[new] = (sin(ImpulseAngle) * ImpulseThrust) + ExternalForceY + (MassOfShip * Vy[current])
Note that the above model assumes a constant External force (constant both in terms of its strength and direction); that is: akin to that of a gravitational field relatively distant from the area displayed (just like say the Earth gravity, considered within the span of a football field). If the scale of the displayed area is big relative to the source(s) of external forces, the middle term of the formulas above should then be modified to include: a trigonometric factor based on the angle between the center of the source and the current position and/or a [reversely] proportional factor based on the distance between the center of the source and the current position.
Similarly, the Ship's mass is assumed to remain constant, it could well be a variable, based say on the mass of the Ship when empty, to which the weight of fuel is removed/added as the game progresses.
Now... All the above assume that the dynamics of the system are controlled by the game designer: essentially choosing a set of values for the parameter mentioned and possibly adding a bit of complexity in the math of the formula (and also ensuring proper scaling to generally "keep" the ship within the display area).
What if instead, the system dynamics were readily programmed into the game (and assumed to be hidden/random), and the task at hand is to write a program which will progressively decide the direction and thrust value of the impulses to drive the ship to its targeted destination, in a way that its velocity at the target be as close as possible to getTargetVelocity()? This is the "Problem A".
This type of problem can be tackled with a PID Controller. In a nuthell, such a controller "decides" which amount of action (in this game's case = which impulse angle and amount of thrust to apply), based on three, weighed, factors, loosely defined below:
how far-off we are the current values from "set point": this is the P=Proportional part of PID
how fast are we approaching the "set point": this is the D=Derivative part of PID
how long and how much have we been away from the "set point": this is the I=Intergral part of PID
A less sophisticated controller could for example only use the proportional factor. This would result in oscillating, sometimes with much amplitude on either side of the set point ("I'm X units away from where I'm supposed to be: let me yank the steering wheel and press on gas"). Such overshooting of the set point are tempered by the Derivative factor ("Yeah, I'm still not where I'm supposed to be but the progress I made since the last time I check is very big: better slow down a bit"). Finally the Integral part takes into account the fact that all things being equal with regards to the combined Proportional and Derivative part, a smaller or bigger action would be appropriate depending on whether we've been "off-track" for a long time or not and of much off track we've been all this time (eg. "Lately we've been tracking rather close to where we're supposed to be, no point in making rash moves")
We can discuss the details implementing PID controllers for the specific needs of the space ship game, if that is effectively what is required. The idea was to provide a flavor of what can be done.
To just get from the current position to the destination with an initial velocity, then apply thrust along the normalized difference between the shortest path and the current velocity. You don't actually need the angle.
-- shortest path minus initial velocity
dx,dy = x0 - x - vx, y0 - y - vy
-- normalize the direction vector
magnitude = sqrt(dx*dx + dy*dy)
dx,dy = dx/magnitude, dy/mangitude
-- apply the thrust in the direction we just calculated
self:applyImpulse(thrust*dx, thrust*dy)
Note that this does not take the target velocity into account because that gets extremely complicated.
I have a very small Lua module for handling 2D vectors in this paste bin. You are welcome to use it. The code above would reduce to:
d = destination - position - velocity
d:normalize()
d = d * thrust
self:applyImpulse(d.x, d.y)
Are you expelling fuel? Your mass will change with time if you are.
Thrust is a reactive force. It's the rate of change of mass, times the speed of the exhaust relative to the spaceship.
Do you have external forces? If you do, these need to enter into your impulse calculation.
Let's assume a magical thrust with no mass being expelled, and no external forces.
Impulse has units of momentum. It's the integral of a force over time.
First off, you'll need to figure out exactly what the API calls "thrust" and impulse. If you're feeding it a thrust multiplied by a scalar (number), then applyImpulse has to do something else to your input to be able to use it as an impulse, because the units don't match up.
Assuming your "thrust" is a force, then you multiply that thrust by the time interval (1/30 second) to get the impulse, and break out the components.
Don't know if I'm answering your question, but hopefully that helps you to understand the physics a bit.
It's easier to think about if you separate the ship's velocity into components, parallel and perpendicular to the target velocity vector.
Considering along the perpendicular axis, the ship wants to come in line with the target position as soon as possible, and then stay there.
Along the parallel axis, it should be accelerating in whatever direction will bring it close to the target velocity. (Obviously if that acceleration takes it away from the target point, you'll need to decide what to do. Fly past the point and then double-back?)
I would deal with the two of them separately, and probably perpendicular first. Once it's working, and if that doesn't prove nice enough, you can start to think about if there are ways to get the ship to fire intelligent angles between perpendicular and parallel.
(EDIT: also, I forgot to mention, this will take some adjustment to deal with the scenario where you are offset a lot in the perpendicular direction but not much in the parallel direction. The important lesson here is to take the components, which gives you useful numbers on which to base a decision.)
Your angle is the Inverse Tangent the Opposite/Adjacent
So angle = InvTan(VY/VX)
No sure what your are talking about concerning wanting to drift??

Resources