Title: J2ME Game API 1
1J2ME Game API 1
2Overview
- There are only five classes in the MIDP game
package GameCanvas, Layer, Sprite, TiledLayer,
and LayerManager. - These five classes are enough to develop games
with a wide range of capabilities.
3Introduction
- MIDP 2.0 brings a new feature, Game API, to help
developers to develop faster user interfaces with
better usability that save device's resources,
like memory. - Problem with the Canvas class.
- Difficult to manage layers
- Hard to predict when the system will call the
paint() method - Delay may occur in capturing key events
4Cast-Based Animation
- The heart of graphics in almost all computer
games is animation. Without animation, there
would be no movement, we just play word games and
trivia games. - Cast-Based Animation involves graphical objects
that move independently of a background.
5Layer Approach
- The basic idea of the Game API is that the game
screen consists of layers. - The background could be on one layer, the road on
another layer, and the hero's super strong ship
on another (as a sprite). - All these layers can be handled separately and
the API even handles the actual drawing of the
layers. - Also the game area is often larger than the
screen and scrolling the screen in the game code
can be a though job.
6Layer Approach
- The Game API provides a view window, which is a
view of the whole game area. - The view window can be moved easily and points in
the view window can be referenced as points on
the actual screen.
7Game Loop
- A game or animation is built by repetitively
executing a piece of code. - In the loop it checks the value of instance
variables and updates the game state accordingly.
- Based on the game state, the code then
draws/paints/repaints the game screen. - The game loop is an infinite loop.
- The code in the loop should allow the current
thread of execution to sleep every few
milliseconds to control the game playing rate.
(in effect, how fast the game screen should be
refreshed).
8Game Loop
- A typical game loop, implemented in GameCanvas
- public class MyGameCanvas extends GameCanvas
- implements Runnable
- public void run()
- Graphics g getGraphics()
- for ()
- // Check for user input
- // Update game state and redraw screen
- flushGraphics()
- try
- Thread.sleep(50)
-
- catch (InterruptedException e)
- /do nothing/
-
-
9GameCanvas
- The GameCanvas class is made useful by extending
the functionality of the Canvas. - It offers three main advantages over Canvas.
- Application has control over exactly when the
display is updated, instead of having to wait for
the system software to call paint(). - It also provides an easy-to-use mechanism
(polling) to query the current keys being pressed
by the user. - GameCanvas used double buffering technique to
avoid flicking in the animation.
10Polling for Key States
- GameCanvas, as targeted for game playing, offers
an alternate method for responding to key
presses. - Instead of waiting for the key event callbacks in
Canvas, GameCanvas offers a method that returns
the current state of the keys - public int getKeyStates()
- This is attractive for games because it gives
your application more control. - By grabbing the current state of the keys (a
technique called polling), you can respond to
user actions within the game loop.
11Polling for Key States
- You could expand the example GameCanvas loop
presented above as follows to respond to key
presses - Graphics g getGraphics()
- While (true)
- // Check for user input.
- int ks getKeyStates()
- if ((ks UP_PRESSED) ! 0)
- moveUp()
- else if ((ks DOWN_PRESSED) ! 0)
- moveDown()
- // ...
- // Update game state.
- // Draw stuff using g.
- flushGraphics()
-
12Example - GameCanvasSimpleDemo
- The man with red pants falls vertically with
random horizontal movement. - The man with black pants controlled by the user.
He can move to left or right only when the user
press the left or right button.
13Example - GameCanvasSimpleDemo
- import javax.microedition.midlet.
- import javax.microedition.lcdui.
- import javax.microedition.lcdui.game.
- import java.util.
- class MyGameCanvas extends GameCanvas implements
Runnable - final static int DISP 5
- boolean isFirst true
- int width getWidth()
- int height getHeight()
- int m_x1 width/2 // runMan 1 move
horizontally - int m_y1 height/2 // y1 never changes
- int m_prevX1 m_x1
- int m_x2 width/2
- int m_y2 height/2
- int m_prevX2 m_x2
- int m_prevY2 m_y2
14Example - GameCanvasSimpleDemo
- Image runMan1
- Image runMan2
- Random generator new Random()
- public MyGameCanvas ()
- super(true)
- try
- runMan1 Image.createImage("/run1.png
") - runMan2 Image.createImage("/run2.png
") -
- catch (Exception e)
- e.printStackTrace()
-
- Thread t new Thread(this)
- t.start()
-
15Example - GameCanvasSimpleDemo
- public void run()
- Graphics g getGraphics() // you
can paint directly! - while(true)
- // Check for user input.
- int ks getKeyStates()
- if ((ks LEFT_PRESSED) ! 0)
- m_x1 - DISP
- else if ((ks RIGHT_PRESSED) ! 0)
- m_x1 DISP
- // clear screen or old images
- g.setColor(0xffffff)
- if (isFirst)
- g.fillRect(0, 0, getWidth(),
getHeight()) - isFirstfalse
-
16Example - GameCanvasSimpleDemo
- else
- g.fillRect(m_prevX1 -
runMan1.getWidth()/2, - m_y1 - runMan1.getHeight()/
2, - runMan1.getWidth(),
- runMan1.getHeight())
- g.fillRect(m_prevX2 -
runMan2.getWidth()/2, - m_prevY2 -
runMan2.getHeight()/2, - runMan2.getWidth(),
- runMan2.getHeight())
-
- // update positions
- m_x2 generator.nextInt()DISP
- if (m_x2 lt 0) m_x2 width
- if (m_x2 gt width) m_x2 - width
- m_y2 DISP
- if (m_y2 lt 0) m_y2 height
- if (m_y2 gt height) m_y2 - height
17Example - GameCanvasSimpleDemo
- if (m_x1 lt 0) m_x1 width
- if (m_x1 gt width) m_x1 - width
- m_prevX1 m_x1
- m_prevX2 m_x2
- m_prevY2 m_y2
- // draw the new the men
- g.drawImage(runMan1, m_x1, m_y1,
Graphics.VCENTERGraphics.HCENTER) - g.drawImage(runMan2, m_x2, m_y2,
- Graphics.VCENTERGraphics.HCENTER)
- flushGraphics()
18Example - GameCanvasSimpleDemo
- try
- Thread.sleep(100) //sleep 100
ms -
- catch (InterruptedException e)
- e.printStackTrace()
-
-
-
-
- public class GameCanvasSimpleDemo extends MIDlet
- public void startApp()
- Displayable d new MyGameCanvas()
- d.addCommand(new Command("Exit",
Command.EXIT, 0)) - d.setCommandListener(new CommandListener()
- public void commandAction(Command c,
Displayable s) - notifyDestroyed()
-
19Layers
- Layers are graphic elements that can be combined
to create a complete scene. - You might, for example, have a background of
mountains, another background of city buildings,
and several smaller items in the foreground
people, spaceships, cars, whatever. - The technique of combining layers is similar to
traditional hand-drawn animations. - Background and foreground images are drawn on
transparent cels, which are placed one on top of
another and photographed to create the final
scene.
20Layers
- Layer is abstract, with two concrete subclasses -
Sprite and TiledLayer. - Layer itself is pretty straightforward. It has a
location, a size, and can be visible or
invisible.
21Layers
- The properties of Layer are accessed and modified
with the following methods - int getX()
- int getY()
- int getWidth()
- int getHeight()
- boolean isVisible()
- void setVisible(boolean visible)
- void setPosition(int x, int y)
- Sets this Layer's position such that its
upper-left corner is located at (x,y). - void move(int dx, int dy)
- Moves this Layer by the specified horizontal and
vertical distances. - abstract void paint(Graphics g)
- Paints this Layer if it is visible.
22Sprite
- The first Layer subclass we will discuss is the
Sprite. - A sprite can be considered as a moving object in
a game. - For instance, a ghost monster in Pac-Man and a
bullet in a shooting game are both considered a
sprite. - The Sprite contains functionality not only for
drawing and moving an image, but also performing - animation,
- collision detection, and
- rotating and flipping the bitmap in various ways.
- First we will examine the basics of the
non-animated Sprite, and then proceed into
animation in the next lecture.
23Managing Layer
- The LayerManager manages a series of Layers.
- The LayerManager will render all the layers under
its control in the correct area and in sequential
order. - In other words it overlaps images over one
another in an easily manageable fashion. - You can think of the ordering of layers as a 3rd
dimension commonly called the z.
24LayerManager
- These layers on z-axis are indexed in a numeric
order starting from zero. - Index 0 is the layer closest to the user
likewise the layer with the highest index value
is furthest from the user.
25View Window
- The LayerManager class provides view window to
control how the game's Layers are rendered. - The view window controls the size of the visible
region and its position. - Changing the position of the view window enables
effects such as scrolling or panning. - For example, to scroll to the right, simply move
the view window's location to the right.
26View Window
- Using view window simplifies scrolling and
panning.
Render to screen
27LayerManager
- In this example, the view window is set to 85 x
85 pixels and is located at (52, 11) in the
LayerManager's coordinate system. - The Layers appear at their respective positions
relative to the LayerManager's origin.
28LayerManager
- For example, if a game uses the top of the screen
to display the current score, the view window may
be rendered at (17, 17) to provide enough space
for the score.
29LayerManager API
- Layers may be added to the bottom of the list
using this method - public void append(Layer l)
- You can add a layer at a specific location using
insert() - public void insert(Layer l, int index)
- For example, you could add a layer to the top of
the list by inserting a layer at index 0. - You can find the number of layers in the
LayerManager by calling getSize(). - If you'd like to retrieve the layer at a certain
position, pass the index to the getLayerAt()
method. - Finally, you can remove a layer by passing the
Layer object to the remove() method.
30LayerManager API
- You can set the view window using the following
method, where the x and y coordinates are
relative to the origin of the LayerManager. - public void setViewWindow(int x, int y, int
width, int height) - To actually draw the scene represented by the
LayerManager's layers, call the paint() method - public void paint(Graphics g, int x, int y)
- The view window of the scene will be drawn using
the given Graphics at the specified location. - Layers are then rendered in the appropriate
order.
31LayerManager Animation - Example
- The HappyFace image moving on a scrolling
background.
32LayerManager Animation - Example
- class AnimationGCanvas extends GameCanvas
- implements Runnable
- final static int DISP 5
- int width getWidth()
- int height getHeight()
- int m_x width/2
- int m_y height/2
- int v_x 0
- int background_w 0
- boolean stop false
- Random generator new Random()
- // Sprites to be used
- private Sprite playerSprite
- private Sprite backgroundSprite
- // Layer Manager
- private LayerManager layerManager
33LayerManager Animation - Example
- public AnimationGCanvas ()
- super(true)
- // Load Images to Sprites
- try
- Image playerImage
Image.createImage("/face.png") - playerSprite new Sprite
(playerImage,20,20) - Image backgroundImage
- Image.createImage("/backg
round.png") - backgroundSprite new
Sprite(backgroundImage) - background_w backgroundImage.getWidt
h() -
- catch (Exception e)
- e.printStackTrace()
-
34LayerManager Animation - Example
- layerManager new LayerManager()
- layerManager.append(playerSprite)
- layerManager.append(backgroundSprite)
- Thread t new Thread(this)
- t.start()
-
- public void run()
- Graphics g getGraphics()
- while(!stop)
- drawScreen(g)
- try
- Thread.sleep(100) //sleep 100
ms -
- catch (InterruptedException e)
- e.printStackTrace()
-
35LayerManager Animation - Example
- // Method to Display Graphics
- private void drawScreen(Graphics g)
- g.setColor(0xffffff)
- g.fillRect(0, 0, getWidth(),
getHeight()) - g.setColor(0x0000ff)
- m_x DISP
- m_y DISP - generator.nextInt()(DISP2)
- if (m_y lt 0) m_y height
- if (m_y gt height) m_y - height
- // updating player sprite position
- playerSprite.setPosition(m_x, m_y)
- v_x DISP
36LayerManager Animation - Example
- // display all layers
- layerManager.setViewWindow(v_x, 0, width,
height) - layerManager.paint(g, 0, 0)
- flushGraphics()
- if (v_x gt background_w - width)
- stop true
-
37TiledLayer
- A TiledLayer is a visual element composed of a
grid of cells that can be filled with a set of
tile images. - The TiledLayer is used to display a large
background graphics in the form of tile maps. - These tile maps can be scrolled, and even
animated for various effects.
38Tiles
- The tiles used to fill the TiledLayer's cells are
provided in a single Image object. - The Image is broken up into a series of
equally-sized tiles the tile size is specified
along with the Image.
39Tiles
- The tiles then can be used to build backgrounds.
40Tile Numebring
- You will notice all tiles have the same
dimensions. - Each tile is given an index numeric value
starting from 1. - The numbering occurs from left to right and top
to bottom. - In other words numbers are assigned row-by-row
bases.
41Creating a TiledLayer
- To create a new TiledLayer use
- public TiledLayer(int columns, int rows,
- Image image, int tileWidth, int tileHeight)
- The TiledLayer's final image will be rows cells
high and columns cells wide. - All cells in the grid are initially empty (i.e.
they contain tile index 0). - To replace the entire tile set after you have
called the constructor simply use the method - void setStaticTileSet(Image image, int tileWidth,
tileHeight)
42Creating a TiledLayer
- public TiledLayer(int columns, int rows,
- Image image, int tileWidth, int tileHeight)
rows 4
columns 12
43Setting the Tile Map
- A TiledLayer is empty when you first create it.
- The TiledLayer object refers to the tile map as
cells. - The cells are just as the two-dimensional array
of tile indices.
44Setting the Tile Map
- You have to set the cell individually by using
- public void setCell(int col, int row, int
tileIndex) - If you set the cell to 0, it will be a blank cell
that is totally transparent. - You can also fill a range of cells with a single
tile index using the method fillCells - public void fillCells(int col, int row, int
numCols, - int numRows, int tileIndex)
45TiledLayer Example
- Build a backgroung using a tile image 1x6 of tile
size 32x32.
46TiledLayer Example
- import javax.microedition.lcdui.
- import javax.microedition.lcdui.game.
- public class ExampleGameCanvas extends GameCanvas
- implements Runnable
- private boolean isPlay // Game Loop runs
when isPlay is true - private long delay // To give thread
consistency - private int width // To hold screen
width - private int height // To hold screen
height - // Layer Manager
- private LayerManager layerManager
- // TiledLayer
- private TiledLayer tiledBackground
47TiledLayer Example
- // Constructor and initialization
- public ExampleGameCanvas() throws Exception
- super(true)
- width getWidth()
- height getHeight()
- delay 20
- tiledBackground initBackground()
- layerManager new LayerManager()
- layerManager.append(tiledBackground)
-
- // Automatically start thread for game loop
- public void start()
- isPlay true
- Thread t new Thread(this)
- t.start()
-
- public void stop() isPlay false
48TiledLayer Example
- // Main Game Loop
- public void run()
- Graphics g getGraphics()
- while (isPlay true)
- input()
- drawScreen(g)
- try
- Thread.sleep(delay)
- catch (InterruptedException ie)
-
-
-
- // Method to Handle User Inputs
- private void input()
- // no inputs
-
49TiledLayer Example
- // Method to Display Graphics
- private void drawScreen(Graphics g)
- g.setColor(0xffffff)
- g.fillRect(0, 0, getWidth(), getHeight())
- g.setColor(0x0000ff)
-
- layerManager.paint(g,0,0)
- flushGraphics()
-
- private TiledLayer initBackground() throws
Exception - int rows 10
- int cols 10
- Image tileImages Image.createImage("/tiles.p
ng") - TiledLayer tiledLayer new TiledLayer(cols,
rows, tileImages,32,32)
50TiledLayer Example
- int map
- 5, 1, 1, 4, 1, 1, 1, 1, 1, 6,
- 5, 1, 3, 1, 1, 3, 1, 1, 1, 6,
- 5, 1, 2, 1, 1, 2, 1, 1, 1, 6,
- 5, 1, 2, 3, 1, 2, 1, 1, 1, 6,
- 5, 1, 4, 2, 1, 2, 1, 1, 1, 6,
- 5, 1, 1, 4, 1, 2, 1, 1, 1, 6,
- 5, 1, 1, 1, 1, 4, 1, 1, 1, 6,
- 5, 1, 1, 1, 1, 1, 1, 1, 1, 6,
- 5, 1, 1, 1, 1, 1, 1, 1, 1, 6,
- 5, 1, 1, 1, 1, 1, 1, 1, 1, 6
-
- for (int i0 i lt rows i)
- for (int j0 j lt cols j)
- tiledLayer.setCell(j, i,
mapicolsj) -
-
- return tiledLayer