2
\$\begingroup\$

I'm a little confused over using integration to move a sprite. This is how I've always achieved this:

float time = 10f;  //Number of seconds to pass a pre-defined area (using the screen width in this example)
float velocity = 1f/time; //work out velocity based on above time
float realX+=velocity*dt; //Move the sprite to the left (where dt is previously defined delta)
x = realX*screenWidth //convert to screen coordinates so it can be rendered

sprite.draw(x, y); //Working out the y position in the same way

Now, with the above code, there are 2 elements that are closely tied. Those being 'time' and 'screenWidth' - (of course, screenWidth could be replaced with another unit of distance such as a tile width in a tile-based game). However, It will always move the sprite at a speed that would take it 'time' (seconds) to cross 'screenWidth' (or whichever unit is specified).

However, I've been looking at various articles on Euler integration such as:

position = position + velocity * dt;
velocity = velocity + ( force / mass ) * dt;

So, the first line is the same my method, but the second line is working out the velocity differently (using force/mass). Also, some examples I've seen have an 'acceleration' variable (which seems logical as I assume you could just then explicitly define the acceleration).

On acceleration

If I need to accelerate a sprite, I have been doing something like this:

time-=.3;

And then working out the velocity again. So I'm using my time component to speed up or slow down my rate of acceleration. Not sure if this is correct.

I'm not great with physics so I would like to know - is my method valid? How would I use EULER with an 'acceleration' variable? Or how does force/mass come into play? Any help anyone could offer would be great.

\$\endgroup\$
2
\$\begingroup\$

You method is valid if it produces the result you want.

That said, you'll likely run into issues as the complexity of your simulation increases. The reason you've seen things like

position = position + velocity * dt;
velocity = velocity + ( force / mass ) * dt;

is because it maps on well to what actually happens in the real world.

The velocity is the derivative of the position, and the acceleration is the derivative of the velocity. That, coupled with the fact that you often don't assign a velocity to a physics object but rather give it an acceleration by giving it a push (applying a force) means that to find the position for the next frame you take the sum of the forces acting on the object and integrate to get the velocity, then from the velocity you get the new position.

Because Newton's laws of motion tells us that F = ma, you can get the a by divinding the sum of the forces by the mass. That will give you the acceleration. The acceleration is scaled by the elapsed time and applied to the velocity. The scale the velocity by time and apply that to the position.

The way force and mass comes into play is that if you model you physics world using the laws (or at least close approximations of) that apply to the real world a lot of things come for "free", by assigning intuitive properties to objects (like density or mass) interactions between object and how the react when subjected to forces makes sense.

As the problem you're trying to solve becomes bigger it becomes more important for the solution to be consistent, in your example you say that to accelerate something you do time-=.3, but to me that doesn't make sense.

I think the answer to the question "How do we make the box move faster?" should be "Push it using a greater force.", not "Pretend less time has passed".

To use an Euler integration with an acceleration variable you would (very simply put);

Have a physics object that looks something like this;

class Body {
  float mass;
  Vector position;
  Vector velocity;
  Vector force;
}

Then, to affect the Body you would apply a force;

body.force += additionalForce;

Then, to move the Body to the new position you would;

void update(float dt, Body body) {
    body.position += body.velocity * dt;
    body.velocity += (body.force / body.mass) * dt;
    body.force = Vector.empty; // Clear out the forces 
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for this detailed answer @Bornader. Using this method, could I still dictate that I want an object to pass a certain distance in a certain time? (As I do with my 'time' variable at the moment?) Or, alternatively, how to I express the speed? (ie, 1 unit per second), so for example, if I have a sprite and I want it to go 10 'units' per second, I would normally set my speed to .1f, (if for example, my 'unit' was a tile rather then the whole screen) then I would know exactly how fast it would move, I hope this makes sense. Thanks! \$\endgroup\$ – BungleBonce Oct 28 '15 at 19:05
  • \$\begingroup\$ One other thing @bornander, what do I set 'mass' and 'force' to initially or how do I work them out? Cheers \$\endgroup\$ – BungleBonce Oct 28 '15 at 20:07
  • \$\begingroup\$ Even using this method you would normally still have methods for setting velocity directly, so if you wanted you body to move by 1 unit per second along the X-axis you would set the velocity to (1, 0, 0) (provided you're in three dimensions). Set 'mass' and 'force' to values that work for you, start with some random value (1 is usually good) and tune it. I use SI-units for my games (so distance is in meters, mass in kg etc, etc), it makes it easy to come up with good values. \$\endgroup\$ – bornander Oct 29 '15 at 7:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.