Monday 22 July 2013

Modelling simple physics behaviour with JBox2D

Now that we are confident that we can add tests to JBox2D's Testbed, it is time to start exploring how we go about modelling a simple world in JBox2D, how we add actors to that world and how we specify how these actors interact with each other.

The MJWTest2, sample test from the previous article was a useful example and a great start, but sooner or later we are going to want to constrain the actors in to a bounded area; let's look at how we go about creating an environment for our actors.

JBox2D doesn't have any detailed, specific technical documentation, but instead directs you towards Box2D's technical documentation - since it is just a port of this library. From the Core Concepts we can see the following useful definitions:
  • World - "A physics world is a collection of bodies, fixtures, and constraints that interact together." 
  • Shape - "A 2D geometrical object, such as a circle or polygon."
  • Rigid body - "A chunk of matter that is so strong that the distance between any two bits of matter on the chunk is constant... we use body interchangeably with rigid body."
  • Fixture - "A fixture binds a shape to a body and adds material properties such as density, friction, and restitution."
These 4 concepts are quite powerful, will be heavily used in and integral to my JBox2D projects, and with these concepts alone there are numerous possibilities.

You can see in the following code (which is an adaptation of the MJWTest2 test) how I've utilised these concepts to create a simple test in which a ball falls from the sky and lands on the ground (the green line) (The complete code can be found on GitHub):

As you can see in the code, we instantiate a World; giving it gravity and setting the centre of gravity.

Note: The world is modelled similar to a graph, with coordinates along the X and the Y axes; with the point where they cross being 0,0. I find it helpful to try and visualise these invisible axes when creating Bodies, initialising their position in the world etc. 

We then create a Body to represent the ground and register it with the World. We decide which Shape we want the ground to be - in this case an EdgeShape, we decide upon the dimensions and location of the ground, and then we affix that Shape to the Body using a Fixture.

  • EdgeShape - "Edge shapes are line segments. These are provided to assist in making a free-form static environment for your game."

The next step is creating the ball and positioning it above the ground waiting to drop. The ball is created in a similar fashion to the ground - instantiating a Body, defining it's location and registering it with the World; choosing a Shape to represent the Body and using a Fixture to bind the two. The one notable difference is that we set the Body's type as dynamic.

From the Box2D technical documentation we see that a Body have have 3 possible types, and that they are defined as follows:
  • Static - "A static body has does not move under simulation and behaves as if it has infinite mass. A static body has zero velocity... Static bodies do not collide with other static or kinematic bodies."
  • Kinematic - "A kinematic body moves under simulation according to its velocity. Kinematic bodies do not respond to forces...  A kinematic body behaves as if it has infinite mass... Kinematic bodies do not collide with other static or kinematic bodies."
  • Dynamic - "A dynamic body is fully simulated. They can be moved manually by the user, but normally they move according to forces. A dynamic body can collide with all body types. A dynamic body always has finite, non-zero mass."
Since we have a non-static Body which we want to collide with the static Body of the ground, the ball is created as a dynamic Body. 

A more complex test

A ball dropping on to the floor is a good start, but it would be nice if the ball had some other material properties (say it was able to bounce), if there were more dynamic Bodies to interact with and if we could introduce Force to model more interesting behaviour. The thought of lots of bouncing Bodies on the screen conjured up images of a moshpit - at least a cross-section of one, so the next progression of my simple test is to model a very simple crowd of jumping Bodies - Moshers.

I also decided that it might be fun to give each of the Bodies slightly different characteristics - how much they weigh, how much friction they have (predominantly this will be with the ground) and how much power is in their, initial*, jump.

The following test is how I modelled a very naive and simplistic version of this scenario (The complete code can be found on GitHub):

You'll notice a slight modification to the "Environment body" section of the code, where I add in walls - to stop the Bodies disappearing off of the screen.

What's more interesting is how you go about dynamically creating, adding material properties and positioning multiple Bodies.

The positioning is all based around factoring in the radius we assigned to the CircleShape (0.9) and the coordinates of our environment. If you place a Body overlapping another Body then the dynamic one (in this case our CircleShapes) will try and push away and detach itself; this is why the first Body in the simulation is located at (-19.1, 0) - the bottom left hand corner of the environment with its left hand side just touching the left hand wall. It's also the reason why I increment the position by 1.805 each time, so that each Mosher has a bit of breathing space*.

I then use select a random index from each of the lists of attributes and assign it to a Mosher to give it some characteristics and set it off moshing.

*A limitation to this simulation is that I currently only know how set an initial Force to act upon each of the Bodies - when it is initialised. And to get around the fact that the Mosher would soon run out of steam, I set the restitution close to the maximum (1), so that they would lose very little energy each bounce. I wanted to add crowd surfers and interaction between the Moshers, but this quickly ends up with a bunch of inactive Bodies, so I will have to leave these features as future enhancements for when I know more about JBox2D.

  • Restitution - "Restitution is used to make objects bounce. The restitution value is usually set to be between 0 and 1. Consider dropping a ball on a table. A value of zero means the ball won't bounce. This is called an inelastic collision. A value of one means the ball's velocity will be exactly reflected. This is called a perfectly elastic collision."

The next thing that I'm interested in looking at is adding the ability for the user to press a button in order to interact with the simulation - this is a necessary step on the road to creating a Pinball Machine. This is part of what I will focus on in the next post - the other thing I will look at is the complex subject of Joints.

Prev (Adding tests to a JBox2D Testbed)    Next (User input and simple Joints)

No comments:

Post a Comment