libGDX Jam Day 13: Physics I

Reading Time: 4 minutes

Back in the Jam!

In my last post, I mentioned that my computer had died- specifically my HDD was dying due to overheating. I did have a USB stick with Ubuntu installed on it, but it has very limited space and fun little quirks (like somehow undoing any customizations or installations I’ve made each time I reboot).

Good news is, in my now-copious spare time, I found a way to get Ubuntu installed onto a larger stick (and for real this time, not a “try it out” version which resets each time). It still has a bunch of crashes and quirks, but I was able to set up my development environment.

All that being said, on to the development!

Adding Physics

During my downtime I spent a lot of time studying entity systems. I like the concept, but the implementation is still a little fuzzy- most of the examples out there are for simple games you can finish in an hour-long presentation. Because I am foolish, I am not making a simple game. Fortunately I was able to garner enough tidbits from my research to figure out how Box2D (and other 3rd party libraries, for that matter) can be integrated with an entity system.

As you probably already know, one of the key principles of an entity or component/entity system is to store all our data into components, and all our logic into systems((N.B. There seems to be a gray area for getters and setters in components, but for the time being I decided not to mess with that.)). Thus, we would normally begin by breaking entities down into the data and systems they need. I’ve taken a first pass at it using the hierarchy below:

Iteration #1

  • “Player Ship” Entity
    • Physics System
      • Bounds Component
      • Player Controller Component
      • Transform Component
      • Movement Component
    • Graphics System
      • Bounds Component1
      • Label Component
      • Texture Component
      • Transform Component
  • “Asteroid” Entity
    • Physics System
      • Bounds Component
      • Transform Component
      • Movement Component
    • Graphics System
      • Bounds Component
      • Texture Component
      • Transform Component

Uh-oh, it looks like we have a problem. If you look at the systems listed for the “Player Ship” and the “Asteroid”, you’ll notice that the asteroids use fewer components than the player ship does. The physics of the player ship are influenced by the player’s input, whereas asteroids don’t care if the player is mashing keys. We can solve this problem by breaking the systems down into more atomic pieces like so:

Iteration #2

  • “Player Ship” Entity
    • Physics System
      • Bounds Component
      • Transform Component
      • Movement Component
    • Engine Control System (If you’ve got a better name, post in the comments below)
      • Player Controller Component
      • Velocity Component
    • Texture Drawing System
      • Bounds Component
      • Texture Component
      • Transform Component
    • Label Drawing System
      • Label Component
      • Transform Component

Now we can share two of the systems across the Asteroid and Player Ship entities, and our two new systems will likely be reused by other entities we come up with.

This leads us to our second problem- Box2D doesn’t give a rip about our components. It has a Body and Shape class which encapsulate bounds, transforms, and velocity. It doesn’t really decompose into the nice little components we have listed above. Best as I can figure, we have several options:

  1. Component: Create a Physics component which holds the physics information for Box2D.
  2. System: Hide the Box2D data structures inside the system.
  3. Hybrid: Create a “light-weight” physics component which contains ‘raw’ physics data, and then use the system method for the Box2D specific objects.
  4. DIY: We build our own physics system that uses the components we want.

Method #1 is the correctest-way, aside from building the physics system ourselves. However, whatever initializes the component/entity will have to have access to the Box2D world and need to know how our physics system works. Method #2 encapsulates all the logic in one place (making it easy to switch out physics systems later), but we’re going with Method #3 because it has the added bonus of giving us more control over which objects have physics (i.e. we can make non-collidable objects by omitting the Physics component).

Implementing Box2D

I wanted to get player input done today, but it turned out Box2D was a large effort on its own.

The first challenge I had was mapping everything out in Box2D. It’s really a Java wrapper around a C++ library, so its structure is a little odd. First, you create a Body Definition object, give it a shape, and then use it to generate the body. After that you create a Fixture Definition and use that to generate a Fixture, which gets added to the body.

I wonder if BodyDef and FixtureDef are some sort of optimization for if you need to generate a bunch of similar physics objects? I’ll need to do some more research into Box2D and see. I might need to pull some of this information into the Physics component after all.

The second issue I ran into was that Box2D “thinks” a little differently than the graphics classes- this is a problem, because I need the hit box to line up with the sprite!

One of the biggest differences was in dealing with position. Box2D likes to use the center of the body or fixture as its position. SpriteBatch likes to use the lower left corner. If you’ve worked with the Sprite class in the past, you may recall that it has setPosition() and setCenter() (lower left corner and center respectively). Box2D uses its Body.setPosition() like Sprite.setCenter().

The other gotcha that had me going for a while was that Box2D thinks in terms of radians, whereas SpriteBatch thinks in terms of degrees. Fortunately the MathUtils class has some helper constants to deal with the conversions.

Overall, I finally got it working, but it would’ve been a lot easier if libGDX had a consistent API. Heck, after today I’d love to code it, but I suspect a change that big would break a lot of code, so I don’t know when/if we’ll ever see that happen.

But at the end of the day, it appears to work, and the code can be found in the “physics-branch” branch until I can clean it up a bit.

Summary

So here’s what I got done these last few days:

  • Fixed a bug that was crashing the debugger.
  • Pulled the background rendering into its own system.
  • Created a Texture System
  • Created a Label System
  • Created the Physics System*
  • Created Entity Factory

*Still need to add player control and collision events.

Screenshot

*Whew*- That was a lot. Thoughts? Suggestions? Let me know below!

  1. This depiction shows “Bounds” multiple times, since multiple systems need to use it. However in reality, the entity will have one shared instance. []