This is a preview before the next improvement
in our "Bob" game.
IMPLEMENTING MOVEMENT IN A GAME LOOP
Since our next step is to implement Bob's jumping ability, I consider it usefull to discuss a few physics aspects before moving on.
The game loop is implementing character's position update every couple of miliseconds. This means that the character doesn't actually move on the screen continuously, but rather at discrete time intervals. However, these intervals are so small that the human eye perceives a continuous movement. So all we need to do is translate some simple mechanics formulas in discrete time.
If you skipped those physics class in high-school , don't worry as it's not at all complicated.
Moving at a constant speed
When moving left and right, Bob's speed is
constant and changing his position is very simple.
Let v be the constant speed
(velocity). A basic, easy to understand formula for the distance traveled at
this speed is:
x =
v*t
where x is the distance traveled in a
time interval equal to t.
How to use this formula?
First of all, you need to pay attention at the
length and time units you use.
In real life, if you are travelling by
car, you measure your speed in miles per hour or kilometers per
hour. Let's say you are driving at v=100 km/h. If you want to know how
much distance can you travel in t=2 hours, simply multiply and get
the result: x = v*t = 100 km/h * 2 h = 200 km. However, if you want
to know the distance for t = 30 minutes, first you must transform minutes
in hours and then multiply: x = 100*0.5 = 50 km. Easy.
In our game, we measure distance not in
meters or kilometers, but rather in pixels. While theoretically correct
would be to go ahead with that and measure Bob's speed in pixels/second,
calculations may become complicated when we try to count the pixels on the
screen and especially since resolution is different between devices.
So in our program we decided to express Bob's
speed in units/second, where a unit has several pixels (depending on the
resolution).
private static
final float SPEED = 4f; // units per second
This means that if you keep the left button
pressed (or equivalent trigger) for a second, Bob will move to the left 4 units
(in our world, 4 blocks).
Now that you understand the formula and the
measuring units, it's easy to compute the "distance" Bob moves at
each update in the game loop:
position.add(velocity.tmp().mul(delta));
As you can see, this function adds to the
current position the "distance" computed inside the paranthesis. To
compute this distance, we use a copy of current velocity's value -
velocity.tmp() - and multiply it with the time delta using velocity object's
method mul.
Moving at continuously changing speed
We only consider the case when the speed
changes uniformly in time. This means that the object has a constant
acceleration.
An example of movement with constant
acceleration that will help you understand better this abstract subject is
movement under gravity. When you let an object fall from your hand, his
speed of dropping towards the earth is not constant, but instead it increases,
meaning the object drops faster and faster.
The physics of acceleration may be rather
complicated so there's no need to get into the details. The only thing worth
mentioning is that the speed follows a similar formula as the position:
v = a*t
where v is the modification in
speed in the time interval t.
I'll go straight to using acceleration in our
game loop.
Since acceleration is an increase (or decrease)
in speed, this means that the update method should not only modify the position
with the formula above, but will also modify the speed. Without writing
any aditional code, we should anticipate that the previous formula used for
constant speed movement will actually be replaced by two similar formulas:
position.add(velocity.tmp().mul(delta));
velocity.add(acceleration.tmp().mul(delta));
I believe the code
to be self-explanatory. First we modify current position using current speed
value, and then we modify the speed's value by adding the product of the
acceleration and the time interval delta.
Obviously, the reason why we use such
complicated statements (instead of simple variables v for
speed, a for acceleration) is because there are two dimensions
to consider! Bob doesn't only move left and right, he can also jump and fall,
so there are two coordinates (left/right, up/down) upon which we need to
compute the modifications. And instead of using two sets of variables for each
coordinate, we choose the built-in class Vector2 which basically does
both in the same time!
This is quick guide to implementing
movement before writing the code. If you need more detailed information about
vectors, I'll gladly write a standalone article about that. Just leave a
comment so I'll know anyone is interested on the subject.
after the physics, i'd like to learn how to make a homepage and a menu :)
ReplyDeleteSure. After I implement movement and jumping, menu comes next since it was in the schedule anyway.
DeleteHey now, don't hog Bogdan, we need to learn some shooting and running animations!
ReplyDeleteAlso, I think that it might be better to use something other than velocity.tmp or acceleration.tmp, as Libgdx gives warnings on using these items. Perhaps using something like this?:
velocity.add(bob.acceleration.x);
position.add(bob.velocity.x * delta, bob.velocity.y * delta );
might have to add or modify some of Bob.java's methods or whatever you call them.
By the way, I would use .cpy() instead of .tmp() for position and velocity changes, because using .tmp() can cause issues when it is being used twice in the same program.
ReplyDeleteOnly now I've seen this post here, but as you suggested later this was modified to act directly on components. Good suggestion though
Delete