Game Physics

In this third step I achieve kitten’s movement. I had to dust off my physics and mathematics schoolbooks and used tons of scratch paper where kittens became arrows, numbers and strange Greek symbols. It was kind of bleak until I saw the real kitten romping around through the screen. At that moment I smiled and added six more kittens and light projecting functionality just for fun.

You may miss Step 2. I avoided to publicize it because it is an intermediate step, but you will find it here.

I recommend you to download the code from github before continue reading.
I’ve inserted some links across the post. Some of these links will guide you to external resources. Other links lead to my code.
I will differentiate my links with this color.
It is important that you keep this in mind because it may be difficult to figure out what am I trying to do without reading the related code.

Summary

In this post, I’ll explain:


1. Physical Objects

This is the heart of the matter. I first thought of a State Machine to implement the movement. I started programming it and everything was going smoothly. But then the verbose boy sitting next to me glanced at my code and said… « Why didn’t you use physical simulation? » Dammit.
That seemed very difficult. Luckily, there’s a great library named Box2D that was created by pleasant physicist for uneducated fools like me. In this post I will explain how I managed to create a physics engine within my mustachioed friends.


1.1. How does it work?

First, we must understand that the kitten is composed by a View and a Model. The view is the Actor and the Nekomata (the stuff that you can actually see on the screen). The model is the ensemble of properties that lies underneath. The view’s behavior must depend on the model’s information, just like our skin moves as a result of our muscles’ work.

My model will be a Body. A body is like a “dummy”. It’s a rag doll with physical properties (like mass, velocity, direction…) that exists in a physical simulation and it’s affected by its environment’s forces. So to move my kitten’s view, I’ll push the dummy and see what happens. Meanwhile, the view will graphically mimic the dummy’s behavior.

You can read a detailed explanation about Bodies here.


1.2. Gathering the pieces of the puzzle

I’ve faced lots of problems this time, but solving them allowed me to use Box2D for my physical simulations:

1.2.1. Box2D’s unit of measurement

1.2.2. The position property.

1.2.3. Time step.

 1.2.4. Velocity

1.2.5. Sensors

1.2.6. Animations


1.2.1. Box2D’s unit of measurement

Box2D measures in meters, GDX uses pixels instead.

To solve this problem, I’ve stored conversion factors on MySettings:

I tried not to use them all over the code, because it could give rise to mistakes and mess it. You will only find them at IPhysicalObject implementations, like DynamicObject. All the measurements will reach as pixels and leave as pixels. Conversions will be held by the IPhysicalObject:

You will also find these conversion factors at BattlefieldStage class, related to the new camera “boxCamera”. This is a little trick. As I said, the world of physical simulation is measured in meters, and the one of the view, in pixels. boxCamera is a camera that films the physics world, so it has a different scale from the one of the view. To solve this problem, I convert the width and height of the box camera to make it proportional.

To say it more appropriately, what I’m doing is to change the Viewport of the box camera:

 


1.2.2. The position property.

modelview_position

 

This is another disaccord between Box2D and GDX. The position property of a body refers to the coordinates of the center of the body. In GDX, the “position” is the bottom left corner’s coords. To fix it, I halve the width and height of the view’s position properties:

As you did with measures conversion, you will only find this calculation inside the IPhysicalObject implementations.


1.2.3. Time step.

The physics simulator (World) takes the time step as a parameter from the screen‘s render loop, this way:

“delta” represents the time it took to run the last render loop. So what I am doing here is to say the world that the time step unity is the delta value. The problem is that this time step may be altered by frame rate fluctuations. The frame rate is the number of frames that are drawn per second. This value can change due to hardware or network failures, because they could increase the delta time, decrementing frame rate.

The potential embarrassing situation will happen when the game freezes for, let’s say, 5 seconds, while I was pushing a kitten with Hulk’s fists. If I would have applied that force for 0.1 seconds, the kitten would move faster for one or two meters. But applying the same force during 5 seconds makes the kitten fly to the International Space Station.

This problem is solved setting a fixed time step, like this:

Here, the render loop accumulates the time step each time it is repeated, and I don’t run the physics simulation until it reaches the fixed time step value.

Imagine it as a trade. The render loop will “buy” the physics simulation. This simulation costs 50. If the render has less than 50, nothing happens, we just draw the view with the current parameters. If the render has 50, I will run one simulation. If suddenly there is a sharp rise in frame rate, and render gets 500, I will run 10 simulations, that means, I’ll see what happens to a dummy-kitten during the next 10 steps of the simulation when it is affected by given forces. I’ve made a graphic: (click to enlarge)

timestep

There’s only one untreated case: What happens with the remainder of the subtraction? When I do timeStep – = FIXED_TIMESTEP, it is quite possible that the timeSteps becomes lower than fixed time step, but higher than zero. What I’ll do with that remainder is to interpolate it.

To do it, I draw the View one step in the past and I interpolate its current position between the last position and the next (present) position. At code:

What saveLastPosition method does for each Kitten’s dynamicBody is this:

And interpolatePositions method (for each Kitten):

interpolatePositions method of the dynamic body:

This will give the kittens a smooth movement. If you run the application, you will notice that the box camera’s (the pink square around the kitten) position is not interpolated, and it “jumps”.

You can learn more about fixing the time step here and here.


1.2.4. Velocity

I’ll first explain how I actually move the kitten’s body. Welcome back to Vector Study subject.

position_vector

This is a position vector. It starts at the origin (0,0) and defines velocity and direction (angle).

In the game, (0,0) will be the initial position of the kitten, and (x,y) will be the destination point (entered by user). The kitten inital position may not be (0,0), so the first thing I do is to move the vector to 0,0 coords:

Then I set the linear velocity:

The problem of doing this is that the velocity depends on the length of the vector, so the kitten moves slower if the user clicks near to him, and faster if the user clicks far from him. He also decreases his speed when he is reaching the destination. And that is disgusting.

I fixed this using unit vectors. I used GDX nor() method to normalize my vectors:

Then I multiplied the resultant unit vector by the fixed velocity I want kittens to move at:

This will give kittens a fixed velocity.


1.2.5. Sensors

The question was… how I can know if the kitten has reached its destination? the Actor’s position is not reliable, because it does not save each and every one of the positions where it has been. It only saves its position each time the render loop is executed.

I started setting ranges, calculating distances, drawing straight lines passing through two points, but none of those solutions where enough reliable/efficient for me.

Then I made a little research and found this post. It talks about Sensors. Sensors will activate a Listener when something happens to the Body, for example, you can use a sensor to know if you body is in contact with another body, or to implement an entity’s vision range.

I won’t extend the above article’s explanation, but I will describe my own implementation. Take a look at this flowchart:

Contact_sensors

First, I attach a ContactListener to the Stage’s model (world).

In my custom ContactListener implementation, WaypointListener, I override beginContact method. This method will receive colliding fixtures. I filter them to do something only when one of the colliding fixtures is a kitten, and the other one is the waypoint related with that specific kitten. When that happens, I inform the kitten.

The kitten executes his onCollide() method, that will set his linear velocity to zero and the “sitting” animation.

A Waypoint, as I will later explain, is a sensor that is thrown to the ground whenever the user stops dragging a kitten. So the kitten will start walking towards the waypoint and when his fluffy paw steps on it, the listener will be activated (and the above execution flow starts).


1.2.6. Animations

If you have already run the program and dragged kittens, you would have notice that the kitten’s animation changes depending on his direction. I made it by assigning different animations to each range of angles:

compass_rose_animations

 

At code:


2. General flow of execution

Now let’s arrange all those pieces to build something that can actually work.

This new version of Fighting Kittens has a Drag Listener that will get the user’s input. This input will tell the kitten the new destination he must start walking to. The Physics simulator will calculate the direction and velocity for this travel, and the View will move according to that information. The kitten will stop moving when he arrives to its new destination. User can also alter kitten’s path at any moment dragging him to a new destination.


2.1. Kitten

This class extends Actor and implements ICollisionable.

As you read at this point, the kitten’s view will mimic the behavior of a body. The body will be affected by forces on a physical world. This is the key of kitten’s movement. Let me show you how I implemented it: (click to enlarge)

Physics_factory

Kitten will ask PhysicalObjectsFactory to build a DynamicObject (that will be the body of the kitten) and a StaticObject (the way point related to that kitten) for him.

I do not know if it’s worth to clarify, but just in case:

A Dynamic Object is an object whose body will be affected by forces at world.

A Static Object will always be motionless.

I think I will have to change this somehow because I could have objects that are static under certain conditions and dynamic in other circumstances. It also exists another type of object, the kinematic object. Emanuele Feronato explains it perfectly in this post:

dynamic body is a body which is affected by world forces and react to collisions. And you already met a million of them.

static body is a body which isn’t affected by world forces it does not react to collisions. It can’t be moved. Fullstop.

kinematic body is an hybrid body which is not affected by forces and collisions like a static body but can moved with a linear velocity like a dynamic body.

 


2.2. KittenDragListener

This class extends DragListener.

So now that we’ve implemented all the bits, there’s only one missing feature: The user’s input handler. I take care of it extending DragListener. I just override the touchUp event to make it:

– Set a waypoint at the coordinates where the user stopped dragging.

– Ask the kitten to start moving to that way point.

Now let the magic happen. 🙂


3. Conclusion

This has been a very intense post! It took me one week to finish this step and write the post. I feel ssssooo exhausted! I’m afraid my code needs a little more refactoring, but I am pretty happy of my creation. I am also learning lots of new concepts, and that makes me feel proud. Besides, this project satisfies my inner need to create, and that’s something that my current job, unfortunately, does not.

Don’t forget to comment and share! See you on my next post.

#FightingKittenBlog

Facebooktwittergoogle_plusredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑