In Which I Figure Out Where To Move Pandas

As feared expected, getting our game done in time for the January 23rd deadline took precedence over writing about all the problems I ran into while making it. However, I will still record the experience here because keeping a record of my journey of discovery will help and inspire future generations of would-be game creators who already know how to program.

When I last left off, I had a cursor on screen, and a pandacat at a fixed location. My next step was to get the pandas to move. Since we knew a central part of gameplay was going to be coaxing animals around obstacles to a specific destination, Josh suggested I look into A* search. I vaguely recalled having studied A* in college and wound up following the excellent article A* Pathfinding for Beginners. The first hurdle I had to cross was deciding the level of detail for my A* grid: our game targets 720p and 1080p TV resolutions,1 but since this game has to run on a decent-but-not-amazing Android device which I have no way of testing with, I figured trying to search pixel-by-pixel was going to use more memory than we had available (not to mention time). I decided to pick an arbitrary reasonable size and landed on 160×90: I figured 10x the aspect ratio of 16:9 would probably give us enough detail.

So, uh, how do I keep track of where the animals can walk and where they can’t?

The LibGDX sample apps came to the rescue again: the Cuboc demo does something very clever to build its level map: it loads a PNG and builds its in-memory level information based on the color values of the pixels in the image. This is probably common practice for a lot of game-dev folks, but this was a new approach to me and struck me as very clever. So I copied it. I made a simple black-and-white image, 160×90 pixels, which showed roughly where the barriers were in our temporary game level. Then I just loaded it into a giant boolean array of arrays in memory (14,400 booleans doesn’t actually take up much memory, thankfully).

A 2x version of the collision map I drew for our basic testing map.

A 2x version of the collision map I drew for our basic testing map.

collisionMatrix = new boolean[160][90];
Pixmap backgroundMap = new Pixmap(Gdx.files.internal("data/warehouse-map.png"));
for (int y = 0; y < 90; y++) {
for (int x = 0; x < 160; x++) {
// Get the pixel, shifting off the alpha value
int pixel = backgroundMap.getPixel(x, y) >>> 8;
if (pixel == 0x000000) {
// true means impassible, also invert y to match our coordinate system
collisionMatrix[x][90 - y] = true;

LibGDX by default counts Y values as increasing from the bottom, so (0, 0) is the bottom left corner, whereas in my image (0, 0) is the upper left, hence the weird Y subtraction.

Now that I knew which grid points where invalid, I could skip them when doing A* searching. Once I fixed a few2 bugs in my A* implementation, I could miraculously draw paths out of grid squares from an animal to an arbitrary location on screen, avoiding obstacles:

The green path is where I want the Panda to go. I just haven't figured out how to get it there yet.

The green path is where I want the Panda to go. I just haven’t figured out how to get it there yet.

Now, I just had to figure out how to tell the animals to move along the path. This turned out to be quite a bit harder than expected, because as I soon learned, I couldn’t remember anything at all about geometry. Next time: VECTOR MATH.

  1. That would be 1280×720 and 1920×1080 respectively. 

  2. okay, a lot 


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s