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. Layer
s 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. TiledLayer
s are used for game backgrounds or much like scenery backdrops in
a theater. It is possible to have several overlapping TiledLayer
s, 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 Layer
s (Sprite
s and TiledLayer
s) 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).