Sunday, June 26, 2011

Box2D game progress

Last night I wrote down a list of things I wanted to get nailed down for my Box2D-based game.

  1. Create a test arena
  2. Create a character actor patterned off of the example written by the libgdx author Mario Zechner (Box2D Platformer Character Controls) and gain understanding of sensor usage.  Additionally, character will have a single arm (ie. an aimed gun) that will shoot projectiles.
  3. Use raytracing to detect where an impact will occur.
  4. Define projectiles
  5. Create response (explosions) at impact points.
  6. Set surface impacts based on the surface - different responses for different surface types
  7. Have effects 'stick' at impact points
  8. Implement a button the character can stand on that opens a remote door.  Closes when the character leaves the button
  9. Create generic actor types that the character can interact with: boxes, elevators, varying gravity fields etc.
I made it through a few of these items and continue to learn lots of cool new stuff.

Creating a test arena was easy enough.  It just consisted of defining a world and supplying static platforms and walls at the periphery.  In the process I got a very good understanding of how OrthographicCamera and PerspectiveCamera's projections work.  Zechner has a very informative and easy to understand overview here.

From there, I started work on the character actor.  The primary shape comes from Zechner's definition in the link above.  I took that and added an arm using a RevoluteJoint.  A RevoluteJoint simply pins two bodies together.  What tripped me up and took a bit of time was that the joint was very...rubber-bandish.  As the character dropped into the arena and the arm caught a platform edge, the arm would get 'stuck' but the character body would continue to descend... It looked like the joint was actually a rubberband.  Here's a picture of the weirdness in action.  The blue line shows the joint (also, I made the arm really long to make getting the effect to happen easier.)

After much debugging, including porting the SliderCrank test from the Box2D C++ TestBed project to libgdx, I finally zeroed in on the density as the culprit.  I had the density of the 'arm' body set to 0.001f.  Bumping this up to 0.5f got rid of the rubber-banding and things started behaving as expected.  This diversion cost me a few hours.

After that, I implemented the capability of firing two different projectiles based on the angle of the arm.  The angle is controlled via the keyboard (atm).  The rotation is implemented via a motor attached to the joint.  When the rotate CW key is pressed the motor speed is set to a predefined > 0 value, and < 0 when the rotate CCW key is pressed. 

When the user hits the 'fire projectile' button, any previous bullet is destroyed and a new bullet is created based on the orientation of the arm using transforms.  To do this, I first create the projectile and then offset the location based on the relation of where the arm was created.  The initial velocity is defined based on this as well.  Then, the velocity vector is rotated following the angle of the arm and the position / angle of the projectile is set according to the arm's transform.

On a side note, one somewhat neat thing about the operation of the character is that I give it a finite impulse upon every jump-key press.  This gives the character the type of motion that you see in the old arcade Joust which is pretty cool looking and fun to mess around with.  This gives me the idea to implement some sort of bird-wing-flapping game.

Here's the current state of the game using the built-in debug renderer.

1 comment:

  1. Is it possible to post the code you had? I have been having some difficulty with revolute joint in libgdx. An example I could tweak might shed the light on what I am doing wrong.