The GameCanvas is a subclass of the Canvas class. GameCanvas adds the following features:
Off-screen graphics buffer
Reading key states (instead of receiving key events)
GameCanvas replaces the repaint and paint mechanism of Canvas with a new getGraphics and flushGraphics mechanism. The getGraphics method returns a Graphics object for drawing into the off-screen graphics buffer, and the flushGraphics method copies the contents of the off-screen graphics buffer to the display.
The getGraphics call returns a new object each time, so in fact it is better to call it once in the constructor of your GameCanvas subclass and keep the result in an instance variable.
The method getKeyStates returns an integer with bits set for each "game" key that is currently pressed. In order that a very short key press doesn't go unnoticed, getKeyStates will have its flag set in the next call, even if the key has already been released by then. This method can be used as shown below:
int keyStates = getKeyStates(); if ((keyStates & LEFT_PRESSED) != 0) sprite.move(-1, 0); // left if ((keyStates & RIGHT_PRESSED) != 0) sprite.move(1, 0); // right
Note that in the above code, if both left and right are pressed, the sprite will be moved both left and right. Not all phones support multiple key presses, but those that do should be taken into account.
A boolean flag suppressKeyEvents in the GameCanvas constructor defines whether key events like keyPressed will be sent for the keys whose states are reported in getKeyStates. Other keys (e.g., number keys not mapped to game actions) will still send key events like keyPressed in either case.
Layer is an abstract class representing a drawable object on the display. Layers can be managed using a LayerManager.
Sprite and TiledLayer are both subclasses of Layer, and it is better to use them rather than subclassing Layer directly.
A Sprite is an animated object that you can move around the screen.
Figure: Sprites
Each Sprite is created from an Image that contains all of its animation frames. The figure below shows an animation frame image of a sheepdog. The image background should be transparent, so that when it is drawn only the sprite itself is drawn.
Figure: Animation frame image, 225 × 15 pixels
Notice that there are no animation frames of the sheepdog running to the right. This is because you can use method setTransform to specify a transform for the sprite to be drawn with: when the sheepdog is running right, use the left-facing animation frames and a horizontal mirror transform (Sprite.TRANS_MIRROR).
Transforms are performed about a reference pixel. By default this is the top left pixel, and if you didn't change this your sheepdog would be reflected 14 pixels to the left of where you expected. Instead, call Sprite method defineReferencePixel and set the reference pixel to be the center of the sprite. Because even-width sprites don't have a single center pixel, it helps to use odd-width sprites.
Class Sprite also has useful methods for detecting whether sprites overlap ("collide with") other sprites. You can use Sprite method defineCollisionRectangle to make the collision detection rectangle slightly smaller than the sprite; this is because if only the edges of two sprites overlap, it usually appears to the player as if they don't overlap yet. It's possible to make the collision detection "pixel level," which means that two sprites are judged to collide only if their opaque (nontransparent) pixels overlap, but this might be slower than just comparing collision rectangles.
For an additional example on using Sprite, see article Rotating images in Java ME in the Nokia Developer Wiki.
A TiledLayer is an object on the screen made up of a rectangular grid of tiles. TiledLayers are used for game backgrounds or much like scenery backdrops in a theater. It is possible to have several overlapping TiledLayers, and to scroll them by just changing their position with the setPosition method.
A TiledLayer has a set of tiles, which is created from an Image.
Figure: Field tile image, 160 × 16 pixels
The figure shows an example tile image. There are ten 16 × 16-pixel static tiles made from this image. The TiledLayer has a 12 × 12 grid of cells, shown in below table. The "land" cells hold values from 1 to 5 for open field, 9 for the brown fold walls, and 10 for the inside of the fold. The "sea" cells hold values from -1 to -3. There are no cells holding value 0 (transparent).
-3 |
-2 |
-3 |
-1 |
-2 |
-1 |
-3 |
-1 |
-2 |
-3 |
-1 |
-2 |
-2 |
3 |
4 |
3 |
1 |
2 |
3 |
2 |
1 |
5 |
2 |
-3 |
-1 |
2 |
1 |
2 |
3 |
4 |
5 |
3 |
2 |
4 |
3 |
1 |
-2 |
1 |
4 |
9 |
9 |
9 |
9 |
4 |
5 |
2 |
1 |
-2 |
-3 |
3 |
5 |
9 |
10 |
10 |
10 |
2 |
1 |
3 |
5 |
-1 |
-2 |
2 |
3 |
9 |
10 |
10 |
10 |
5 |
4 |
2 |
1 |
-3 |
-1 |
4 |
2 |
9 |
9 |
9 |
9 |
3 |
1 |
3 |
2 |
-2 |
-3 |
2 |
5 |
1 |
3 |
1 |
4 |
2 |
5 |
4 |
3 |
-3 |
-2 |
1 |
4 |
2 |
5 |
2 |
3 |
4 |
2 |
1 |
3 |
-1 |
-1 |
5 |
1 |
4 |
3 |
4 |
1 |
2 |
3 |
4 |
1 |
-2 |
-3 |
2 |
4 |
5 |
2 |
3 |
2 |
4 |
1 |
2 |
3 |
-3 |
-2 |
-3 |
2 |
-1 |
-2 |
-1 |
-3 |
-2 |
-1 |
-3 |
-1 |
-2 |
The resulting TiledLayer is shown in the figure below.
Figure: TiledLayer field
The cell values -1 to -3 are animated tiles, created using TiledLayer method createAnimatedTile. Each points to one of the blue sea static tiles numbered 6 to 8. By continuously changing which static tile each points to, you can make the sea move without changing the grid cell values themselves.
Class LayerManager allows you to manage all of your Layers (Sprites and TiledLayers) easily. Simply add them all to your LayerManager, then instead of painting them all individually just tell the LayerManager to paint. The LayerManager keeps track of their "Z-order" (by default, layers added later are nearer the back).