Ms. MIDP-Man: Technical stuff

I tried to keep the program structure simple. Nearly everything important is contained in a class called MazeCanvas, which is a subclass of the MIDP 2.0 GameCanvas class. Outside it is the MIDlet subclass, MsMIDPMan, whose only job is to start up a MazeCanvas and shut it down when the game ends. I also have a small class called MazeObject, which holds relevant information about mobile maze objects, such as direction, speed, look and position. And finally I added a class called Blipper, named for its use to play "blip" sounds when Ms. MIDP-Man eats a dot. Doing it in the same game loop as the action resulted in jerky motion on at least one phone model, because of some kind of system delay whenever a sound starts. So I decided to put all sound management into a separate Thread subclass. This worked much better.

Like most other games of its time, the original used 8x8-pixel tiles for the backgrounds (including the "font"). I identified all of the necessary building blocks and created my own tile set, to be used for a TiledLayer object. But I don't save them as an ordinary PNG image file. Instead I use a one-byte-per-pixel "raw" format, to make it easier to set custom colors inside the game. Each maze is also a separate file, in which the first 9 bytes hold the RGB values of the dot, outline and wall colors. The rest is just the tile data in reading order, padded with three extra bytes at the start and end of each row, so that the mobile objects have some room to move outside the maze when they use tunnels.

This is what the tile set image looks like when it's been given the colors of the first level (magnified to 200% for clarity):

The first 20 tiles do not obstruct motion. I let the game characters move freely on top of them, but any tile with a value above 20 is considered a wall (the only exception being the door to the ghost house).

And this is my graphical sprite data (also magnified, and shown against a dark background for clarity):

Each "frame" is 16x16 pixels. The game uses one Sprite object to hold all of these, which I then rubber stamp in the appropriate place for each mobile object. I could have used one Sprite per object and kept them all in a LayerManager, but that seemed redundant.

The motion of the game characters is of course one of the most important parts of the game. With the exception of when the ghosts go in and out of the house (which is simple enough to be handled as a special case), everything is confined to an 8x8-pixel grid and can only change directions at exact 8-pixel intervals. So when I move the characters, I have to make sure that their steps always add up to 8-pixel multiples, or they will fall out of grid alignment. (For example 1+2+1+1+2+1 for slow movement and 4+4 for very fast.) As a side effect, I can only safely change speeds at perfect 8-pixel multiples as well -- like when the ghosts turn blue or become free-floating eyes. Then they have to wait until the next 8-pixel multiple before their speed chatches up.

Few things could be simpler than the basic principle of motion for the ghosts and fruit: find a random available direction, but not opposite to the one you had in the previous step, except when that's the only alternative. (And the last "except" is just because I allow, in theory, for mazes that have dead ends. The original Ms. Pac-Man has no such things, so it's not an issue.) This somehow gives the illusion of "purpose" to the object's path. For the ghosts I amend this rule with one that says that the new direction can't be perpendicular to the previous one and lead away from Ms. MIDP-Man. (Scared ghosts can't pick a perpendicular direction that leads closer to her.) It's not perfect, but enough to make the game challenging.

Making the ghosts find their way back into to the house after they've been eaten was a bit more difficult. Again, allowing in theory for more complicated mazes than in Ms. Pac-Man, I solved it with the same homing algorithm I used in Dungeon Dregs. I've called this the "bread crumb" technique. The ghosts follow a trail (in a separate array the same size as the maze) back to the front door of their house. Once there, moving inside can be handled as a separate case.

And finally, I have tested this game with excellent results on various small-to-medium-sized screen Sony Ericsson phones (like the K610i on the main page), but if you intend to run it on different brands, there are a few things you should keep in mind:

  • Obviously it needs to support MIDP 2.0.
  • Don't bother if the screen is smaller than 128x128 pixels. Then there won't be enough vertical room for the intro sequence or not enough horizontal room for both the score and the highscore.
  • Not all phones can handle WAV files (sampled sounds). For example the Nokia 6230 will crash if you try. Then you need to remove some of the sound-playing method calls, or replace the effects with MIDI files.
  • Some cery old phones, although capable of running the game in theory, are just too slow. Like the Nokia 6600. Then the default setting of 50 milliseconds per animation frame must be adjusted up a bit (fewer FPS), and the game characters should take bigger steps to compensate for this.
  • I use GAME_B_PRESSED as the exit button. On for example the SonyEricsson K700i this maps to the '9' key. Other phones may have a more logical choice.