You are on page 1of 31

• Download Basics - 59.

88 KB

Introduction
This article is the first part in my Mobile Game Programing for Beginners series. The
series start out with a super-simple game but will continue to show how to implement a
variety of different game types and the techniques used to code them.

The series is a four part series where I'll go through the following games:

• Basics
• BreakOut
• Top Down Scroller
• 3D Space Game

This part will show you how to implement a very simple game, which tools you'll need
and how to actually try it out on your handset.

In this game, the goal is to navigate your avatar to a target, no obstacles and the target
isn't even moving. There's no way to "die", no way to loose, but it's a good starting point
to show the basics of game programming. The areas I'll cover in this first part are:

• Tools of the Trade, the applications required (or at least the ones I like to use).
• Creating a MIDlet, an application that can run on your mobile phone.
• Basic Game Loop, the foundation of any game.
• Reading user input.

Tools of the Trade


All the games in this series have been developed using three software packages:

• Java 6 SDK
• NetBeans
• Paint.NET

Java 6 SDK

The Java SDK (or JDK, Java Development Kit) is a collection of class libaries, tools and
documentation used when developing Java applications. It is not to be confused with a
JRE, Java Runtime Environment, which is something that is used to run Java based
application. I downloaded my JDK from here. You'll need a JDK installed to use the next
tool on the list, NetBeans, so make sure this is the first thing you download.

NetBeans

NetBeans is an Integrated Development Environment, IDE, mainly for Java development.


It is free, which is good, but the best thing about it is that it truly rocks. According to me
it's by far the best Java IDE around right now.
NetBeans is the tool that you'll use to implement and test your game as it comes bundles
with a neat emulator so that you don't have to install the game on your mobile phone
before you know it works.

Go here and download the Mobility pack and get that installed. The Mobility pack
includes the J2ME JDK (Java 2 Mobile Edition), which contains the class libraries
required to write a MIDlet (which is a java application that can run on a mobile device),
and the tools required (such as emulators for testing the game without having to install it
on an actual handset).

Paint.NET

Almost all games needs some sort of graphics to make them enjoyable, I prefer to use
Paint.NET to create the graphics for my games (when it's not generated by the game
itself, but more on that in the second part of the series). The reason I'm not using Paint
that comes bundles with windows is that it's simply not packed with all the nice features
that Paint.NET have, such as support for transparent png files.

Head on over to Paint.NET's download page and download it.

Once you have these three tools installed you're almost ready to start coding.
Basic Game Loop
Almost all games rely on a central game loop, it is the loop that manages or control the
game. As the games you write become more and more complicated the methods called
from the game loop will have to contain more and more logic, but the actual game loop
will still be a fairly simple loop. In its simplest form it might look something like this:

Collapse
while(gameShouldStillBeRunning) {
// Capture input
readInput();

// Update the game state


updateGameState();

// Present the game to the user, i. e. render or draw it to screen


renderGameState();

// Check for game over


checkGameState();
}

Reading Input

This method is responsible for reading or capturing the current state of the input. This
includes for example checking which keys are pressed and how far the mouse has moved
since last check. The method typically stores the input that is relevant to the game in a
place where the updateGameState method can access it.

Storing the game state can be as easy as setting a boolean value to true if a key is pressed
and to false it it's not pressed. The reason for checking the input and storing it first,
instead of checking it when you actually need it (i.e when updating the game state), is
because it is often quite expensive CPU wise to read the input and it is best to get all the
input required at once. Otherwise different parts of the code that updates the game state
might query the OS several times for the same key input, which would be unecessary.
Making the games run smooth and fast is a major part of game development and I will
discuss this in a later part of this series.

You'll notice that the game included in this article doesn't read the input state in the game
loop, that is because it's relying on a built in functionality of the
javax.microedition.lcdui.Canvas, more on this later.

Update Game State

Updating the game state include all the actual processing of the game logic, such as
moving the players character according to the input captured, moving enemies according
to their AI, updating the environment, checking for game over state and many more
things all depending on what kind of game is being developed.

In this first part, updating the game state includes only moving the avatar and checking if
the avatar has reached the goal.

Render Game State

When the game state is rendered the state of the game (i.e. location of the player, the map
and for example the current score) is drawn to the screen.
The Canvas class in the javax.microedition.lcdui package is used to render things to
the screen in kind of the same way as java.awt or javax.swing components, by
overriding the Canvas.paint(Graphics graphics).
Note that the Graphics parameter isn't the java.awt.Graphics object that you might
reconize from desktop development, it is a javax.microedition.lcdui.Graphics
object, which is like a cut down version of the AWT one.

Check for Game Over

This is where the game primarily detects if the player has lost or beaten the game, but it
will also detect and act on any major state changes. Such as completing a level and
moving into a game state where the level summary is shown before the next level is
started (yet another state).

Getting Started
Setting up the Project

The first thing to do to get started is setting up a project in NetBeans, it is important to


pick the right type of project as the project type dictates the JDK that will be used
(remember we need the J2ME JDK to get this to run on a mobile device).

Create a MIDP Application Project

In NetBeans, select File->New Project... and select project category Mobility and projec
MIDP Application, then click Next.
Give your project a name, in this example it is called Basics.GameLoop. Then make sure
to un-tick the Create Hello MIDlet as that will create a template designed to handle a
Control based UI (with buttons and lists), and for a game all rendering is custom so no
standard controls will be used. Then click Next.

The next screen shows configuration options, the settings picked here must match the
target device's capabilities. That means that a game written for MIDP-2.1 will not run on
a mobile phone that only supports MIDP-1.0 for example. For now leave this page with
it's default settings and click Finish.
In your new project's source package create a package (as keeping classes in the root
package is discouraged), you can call the package whatever you want, in the example
application it is called com.bornander.games.basics.

Create a class called BasicsMIDletin the package you just created, this will be the entry
point for the application. This is the class that the Java runtime on the mobile device will
instanciate when the the user selects your midlet. Make sure the BasicsMIDlet class
extends javax.microedition.midlet.MIDlet, as this class defines the interface used
by the runtime to control a midlet.
The javax.microedition.midlet.MIDlet is an abstract class and there are three
methods that must be overridden:

startApp()
This method is called by the runtime to start the midlet, either when a start is requested
by the user by selecting the midlet in some menu or when a the mobile device decides to
return control back to a previously paused midlet.

pauseApp()
This method is called by the runtime to indicate to an midlet that it will loose focus,
possibly due to an incomming call. It is entirely up to the midlet to actually pause
something, the example game included in this article will ignore this method which
means the game would continue to run when a call comes in.
If a midlet decides to pause itself is should, after taken steps to suspend itself in a
controled manner, call resumeRequest() method to notify the framework that it is
interested to know when it can resume processing.

destroyApp(boolean conditional)
This method is called when a midlet is being destroyed (closed), to allow it to clean up its
resources in a safe and controlled way.

Make sure your BasicsMIDlet implements these three, abstract methods, after which
your class should look something like this:
Collapse
package com.bornander.games.basics;
import javax.microedition.midlet.MIDlet;

public class BasicsMIDlet extends MIDlet {

public BasicsMIDlet() {
}

public void startApp() {


}

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}
}

The next step is to add the the MIDlet to the Application Descriptor, which is a set of
meta data that holds information about the mobile application. One mobile application
can contain several MIDlets but for this example there's only going to be one.

Right-click the Basics.GameLoop and click Properties, then select Application


Descriptor, the MIDlets tab and click Add.... This will let you select a MIDlet class,
give it a name and icon and add it to the descriptor. The dialog auto-detects classes that
extends javax.microedition.midlet.MIDlet so just click Ok to accept the default
proposal.

And that's it! The mobile application is created, click Run Main Project to try it out on
the emulator, this will launch a mobile phone emulator from where the MIDlet just
created can be started. Note that since there's no actual implementation yet it won't do
anything. Add a System.out.println("Hello, world!"); to the
BasicMIDlet.startApp method and run the application again to see that it's actually
started. The text will be printed to NetBeans IDE so do not expect to see it on the screen
of the emulator.

Rendering to screen

When writing MIDlets there's a set of classes for labels, text fields, checkboxes and such
that are used in a similar way to the corresponding classes in Swing or AWT. As this
article is about game programming it won't discuss any of these controls as they're not
very well suited for graphical games.

The class used to render to screen in javax.microedition.lcdui.Canvas, by extending


this class it is possible to override its paint method and implement custom rendering.
Create a new class called MainCanvas and have it extend
javax.microedition.lcdui.Canvas. Override paint to render red text on blue
background:

Collapse
package com.bornander.games.basics;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

public class MainCanvas extends Canvas implements Runnable {

public MainCanvas() {
}

// The Graphics object is used to render images, lines, shapes and


// text to the screen using different draw methods.
protected void paint(Graphics graphics) {

// Get the width and height of the screen in pixels


int w = getWidth();
int h = getHeight();

// Set the current color to blue (hex RGB value ) and draw a
filled
// rectangle the size of the screen
graphics.setColor(0x00007F);
graphics.fillRect(0, 0, w, h);

// Set the current color to red, the font to the default font
and
// draw a string to the center of the screen.
graphics.setColor(0xFF0000);
graphics.setFont(Font.getDefaultFont());
graphics.drawString("Hello, world!", w / 2, h / 2,
Graphics.BASELINE | Graphics.HCENTER);
}
}

In order to get the MIDlet to use this Canvas it has to be set as the current one for the
display. Modify BasicMIDlet.startApp to create a MainCanvas and set it to the default
Display:

Collapse
public void startApp() {
MainCanvas mainCanvas = new MainCanvas();
Display.getDisplay(this).setCurrent(mainCanvas);
}

Run the MIDlet again, this time is should look something like this:

Now it's time to start implementing the actual game.

Implementing the Game


Loading resources

Even though it would be possible to render all aspects of a game using the different draw
methods on the javax.microedition.lcdui.Graphics it is more common to use
images created in a image editing program (such as Paint.NET). This game will use two
different images, one for the player or avatar and one for the target.

Avatar:

Target:

When creating images it is important to make use of transparent pixels otherwise the
avatar image wouldn't appear to be round but square.

By adding the resources to a Java package it is possible to load them into


javax.microedition.lcdui.Image objects which can then be drawn onto the
javax.microedition.lcdui.Graphics. A convienient way of loading resources is to
use the Class.getResourceAsStream method as it allows for referencing resources
using java package names (but with forward slashes instead of dots). Also, since the
easiest way to get a Class instance is to call Object.getClass, there's always a simple
way to reference resources in the same bundle as the current class.
Image resource can therefore be placed in the normal java package structure:

By adding two javax.microedition.lcdui.Images as members to the MainCanvas,


and loading the resources in the constructor the paint method can be modified to draw
the avatar in the upper left corner and the target in the lower right.
Notice that it's good practice not to use absolute coordinates (such as 100, 100), but
instead calcualte the coordinates based on the current screen width and height. Obviously
0, 0 is always going to be the upper left corner, but the coordinates of the lower right will
vary on different mobile devices. By finding the widht and height of the screen, and then
subtracting the width and height of the image, the target image is guaranteed to always
appear in the lower right corner, regardless of screeen resolution.

Collapse
package com.bornander.games.basics;

import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class MainCanvas extends Canvas implements Runnable {

// Declare members for the images


private Image avatar;
private Image target;

public MainCanvas() throws IOException {


// Load the image resources
avatar = Image.createImage(
getClass().getResourceAsStream("/com/bornander/games/basics
/resources/avatar.png"));
target = Image.createImage(
getClass().getResourceAsStream("/com/bornander/games/basics
/resources/target.png"));
}

protected void paint(Graphics graphics) {

int w = getWidth();
int h = getHeight();

graphics.setColor(0x00007F);
graphics.fillRect(0, 0, w, h);

// Draw the images


graphics.drawImage(avatar, 0, 0, 0);
graphics.drawImage(target, w - target.getWidth(), h -
target.getHeight();

graphics.setColor(0xFF0000);
graphics.setFont(Font.getDefaultFont());
graphics.drawString("Hello, world!", w / 2, h / 2,
Graphics.BASELINE | Graphics.HCENTER);

}
}

Making the Avatar controllable


Always painting the Avatar in the upper left corner isn't going to make for a very
interesting game, by declaring members for position and also travel direction it will be
possible to control the Avatar using the keypad.
Normally I'd prefer to store the location of a Avatar in 2D space as some sort of Point
object, but as the J2ME libraries is a cut down version of the J2SE there is no such class.
I could have written my own (as I have for the other games in this series), but decided to
store the position as two seperate integers. I store the direction as four seperate booleans,
for up, down, left and right.

Collapse
public class MainCanvas extends Canvas implements Runnable {

// The two images


private Image avatar;
private Image target;

// The coordinates of the player.


private int x = 0;
private int y = 0;

// Flags indicating which buttons are pressed.


private boolean up = false;
private boolean down = false;
private boolean left = false;
private boolean right = false;

...
}

Moving the avatar (i.e. updating it's X and Y coordinates according to the directon flags)
is delegated to a method that also does constraint checking. By constraint checking I
mean the process in which the position is constained to a valid one. In this example it is
invalid for the avatar to be outside the bounds of the screen.

Collapse
public class MainCanvas extends Canvas implements Runnable {

...

private void moveAvatar() {


if (up)
--y;
if (down)
++y;
if (left)
--x;
if (right)
++x;

if (y < 0)
y = 0;
if (y > getHeight() - avatar.getHeight())
y = getHeight() - avatar.getHeight();

if (x < 0)
x = 0;
if (x > getWidth() - avatar.getWidth())
x = getWidth() - avatar.getWidth();
}
}

Notice again the use of getWidth/getHeight and avatar.getWidth/avatar.getHeight


to make the constraint checking indenpendent of screen size as well as image size.
This method, MainCanvas.moveAvatar. will be called by the game loop for each
iteration to update the position of the player.
Obviously this also requires a small change to the MainCanvas.paint method, as the
avatar is no longer drawn at (0, 0) but at (x, y).

Capturing the Input

By extending Canvas it's easy to capture input by simply overriding some methods.
Canvas exposes three methods related to key input:

• void keyPressed(int keyCode)


• void keyReleased(int keyCode)
• void keyRepeated(int keyCode)

In this first example I'm only going to use the keyPressed and keyReleased, and to
control the Avatar the only thing the methods needs to is to set the up, down, left and
right according to which key was pressed or released.

The keyCode parameter passed to the key handling can be converted to key codes better
suited for game programming using the aptly named function Canvas.getGameAction,
this will convert the key code into one that can be checked for buttons such as up and
down.

Collapse
/**
* This gets called for us whenever a key is pressed.
* @param key The pressed key.
*/
protected void keyPressed(int key) {
int gameKey = getGameAction(key);
switch(gameKey) {
case Canvas.UP: up = true; break;
case Canvas.DOWN: down = true; break;
case Canvas.LEFT: left = true; break;
case Canvas.RIGHT: right = true; break;
case Canvas.FIRE: shouldRun = false; break;
}
}

/**
* This gets called for us whenever a key is released.
* @param key The released key.
*/
protected void keyReleased(int key) {
int gameKey = getGameAction(key);
switch(gameKey) {
case Canvas.UP: up = false; break;
case Canvas.DOWN: down = false; break;
case Canvas.LEFT: left = false; break;
case Canvas.RIGHT: right = false; break;
}
}

Checking for Game Over state

All games needs to check the Game Over state, this can occur either when the player
loses the game or when he beats it, in any case it has to be checked or the game can
neither be won or lost.

In this first example Game Over can only occur when the player has beaten the game,
yep, that's right; this is a game you can't fail at. You can choose not to win, but you can't
lose. This implementation calls a method called isGameCompleted to check if the game
is over, this method sets a member variable completed.
To change the behaviour of the game when the Game Over state is reached, the run
method looks at the completed flag set when the Avatar has reached the Goal and if it's
true then the Avatar isn't moved anymore, regardless of key presses. Also, the paint
message draws a Game Over message at the center of the screen.

Collapse
/**
* Detects if the game has been completed (i.e. the avatar has
navigated to the target).
* @return true if the game is completed.
*/
private boolean isGameCompleted() {
return x == targetX && y == targetY;
}

This method is called in the run method.

Collapse
protected void paint(Graphics graphics) {

...

if (completed) {
graphics.setColor(0xA0A0FF);
graphics.setFont(Font.getDefaultFont());
graphics.drawString("Game Over", w / 2, h / 2,
Graphics.BASELINE | Graphics.HCENTER);
}
}

public void run() {


while(shouldRun) {
completed = isGameCompleted();

if (!completed) {
moveAvatar();
}

repaint();

try {
Thread.sleep(20);
}
catch (InterruptedException ex) {
}
}
owner.exit();
}

And that's it! That's the whole game, it's not the most addictive game in the world but it is
enough to show how to set up a Netbeans project and the basics of a game.

Next Part
In the next part I'll cover menus, simple AI and basic collision detection as I demonstrate
how to write a BreakOut style game.
As always, any comments on the article or the code are most welcome.

• Download BrickBreaker - 172.36 KB


Introduction
This article is the second part in my Mobile Game Programing for Beginners series. The
series start out with a super-simple game but will continue to show how to implement a
variety of different game types and the techniques used to code them.

The series is a four part series where I'll go through the following games:

• Basics
• Break Out style
• Top Down Scroller
• 3D Space Game

This part will show you how to implement a break out style game.

In this game, the goal is to bounce a ball off a paddle and have the ball collide with
"bricks", if the player fails to block the ball with the paddle the game is over. When the
ball collides with brick, the brick is removed. When all bricks are removed the player has
beaten the game. In this part I'll discuss the following topics:

• Menus and in-game menus


• AI or computer controlled players
• Collision detection

This game, even though it's still a very simple game is far more complicated to write, and
that's why this example consists of 20 classes rather than 2 as in the previous part of this
series. Most of the classes, however, are generic and can be reused in other projects so it's
not as complicated as it looks. I won't show code extracts for all classes in this article but
I've commented the classes that are available for download so for classes or concepts that
I don't discuss in this article; please refer to the code comments instead.

Class Overview
The most important classes in this example are:

• MainCanvas
Initializes the game's screens and controls the updates, rendering and transitions
between the screens.
• BrickBreakerScreen
The class that contains the game logic.
• Ball
Controls the ball's movment, collision detection and rendering.
• Brick
Representation of a single brick.
• BrickField
Representation of all bricks in the game.
• Paddle
Representation paddle, note that this class relies on a PaddleController to
actually control the paddle.
• PaddleController
Interface that's implemented by ComputerPaddleController and
HumanPaddleController in order to allow either a human or a computer AI to
control the paddle.
• MenuScreen
Implementation of simple, generic game menu.
Menus
I love writing games but there's one thing I don't like about it and that's writing all the
little bits and pieces that aren't actually part of the game play, such as menus and in game
dialog boxes. It it, however, quite important to take the time to implement those parts as
well, otherwise the game won't feel polished and there's going to be no way for the user
to configure game settings.

That's why in this part I'll spend some time showing you how to implement a game menu
and how to handle transitions from rendering the menu to rendering the game. As the
game implemented in this part of the series is a simple break out style game, there aren't
really that many menu options but it's still important to have a menu in order to make the
game feel more complete.

Screen transitions

In order to go from rendering the menu to render the actual game, the game must be able
to handle different types of screens, the MIDlet could be used to swap between different
Canvases but I prefer to always use just one GameCanvas that maintains it's of set of
GameScreens.

GameScreen

The GameScreen class is an abstract class that exposes a few method required by my
main MIDlet class in order to control and update the GameScreen's state and request it to
render itself.

Collapse
package com.bornander.games.utils;

import javax.microedition.lcdui.Graphics;

public abstract class GameScreen {

protected Background background;


protected int width;
protected int height;

public GameScreen(int width, int height) {


this.width = width;
this.height = height;
this.background = null;
}

public void setBackground(Background background) {


this.background = background;
}

protected void paintBackground(Graphics graphics) {


if (background != null)
background.paint(graphics);
}

public abstract void activated(GameScreen previousScreen);

public abstract void paint(Graphics graphics);

public abstract int doUpdate();

public abstract void keyPressed(int keyCode, int gameAction);

public abstract void keyReleased(int keyCode, int gameAction);


}

By using a construct such as this GameScreen class, it's easy to write a quite simple
Canvas implementation (I call mine the main canvas) that can initialize the game's
required screens and then handle the transitions between them depending on the logic
local to the active screen.
The game starts up with the menu screen as active screen, and that screen can request the
main canvas to change screen to the actual game screen when the relevant menu option is
selected. That way, the actual implementation of the menu GameScreen can be made
completely generic and it can be re-used for other games. Something which I really like,
because as I said I don't like writing the menus very much.
In this example there's a utility class called MenuScreen that is a generic implementation
of a menu and I'll be reusing that for my other two parts in this series.

MenuScreen
The MenuScreen class is a fairly simple implementation of the GameScreen class, it
allows the programmer to define a set of menu options and then renders these based on
key presses. It handles both simple items and "multiple choice" items (such as Sound
on/off). The MenuScreen itself has no knowledge of the actual game so it can't directly
configure it, but it is possible for the game to retrive the settings from the previous screen
as that is passed as an argument when a screen transisition occurs.

In-game dialogs

Sometimes there's a need to interrupt the game and present the player with information
and/or options during the game. In these scenarios it's neater to present a in-game dialog
rather than taking the user back to a fully fledged menu screen. That means that the actual
game screen handles the transitions between playing the game and showing the dialog
and the main canvas has nothing to do with this type of transition.

One such situation is when the user pauses the game, which in this example is done by
clicking the Fire button. When the game enters the the paused state it stops updating the
paddle's and ball's position, it still renders them but it also renders a dialog box in the
foreground. The game state change from running to paused also changes how input is
handled; in running mode pressing Up or Down adjusts the sound volume, but in paused
state it resumes or returns to the main menu instead.

The different states that the BrickBreakerScreen class uses are:

• Starting
When the game is starting up, this gives the player a bit of time to prepare.
• Running
When the game is in play.
• Stopped
The game enters this state when it's game over.
• Paused
The the user has paused the game.

This states are defined as simple ints in BrickBreakerScreen:

Collapse
public class BrickBreakerScreen extends GameScreen {

...

// The different game states


private final static int GAME_STATE_STARTING = 0;
private final static int GAME_STATE_RUNNING = 1;
private final static int GAME_STATE_STOPPED = 2;
private final static int GAME_STATE_PAUSED = 3;

...
}

AI
An important part of most games is computer opponents that behave intelligently, and
while a break out game probably isn't the first game that comes to mind when discussing
AI I think it's a good place to start as the actual AI is easy to implement (the paddle can
only move right or left). It will also allow me to show how using a well abstracted class
design not only makes it easy to create a computer controlled entity in the game, it can
also makes it easier to debug and to add network support.

Abstracting the controller

The AI in this game is simply the computer trying to control the paddle, and like I said,
this is a fairly easy task as there are only a few things the paddle can do:

• Move left
• Move right
• Don't move at all

The information the AI uses to decide which these options to go for are:

• Position of the ball


• Position and size of the paddle
One can argue that the velocity of the ball should be an input as well but for simplicity's
sake I'll ignore that for now.
This information is the same information a human would use, the difference is that the
human needs to input the choice using the keys, therefore if an interface was created that
would allow the above information to be consumed and the output (left, right, don't
move) produced as well as taking into account the key presses then that interface would
apply for both the human controller and the computer controller.
I decided to call the interface PaddleController:

Collapse
public interface PaddleController {

public static final int COMMAND_NOTHING = 0;


public static final int COMMAND_MOVE_LEFT = 1;
public static final int COMMAND_MOVE_RIGHT = 2;

void initialize();

void updatePaddleData(int x, int y, int width);

void updateBall(int x, int y, int deltaX, int deltaY);

void keyPressed(int keyCode, int gameAction);

void keyReleased(int keyCode, int gameAction);

int getCommand();
}

Information about ball and paddle are provided to the controller using the
updatePaddleData and updateBall methods, information about key presses are
captured using keyPressed and keyReleased and the getCommand method return the
action.

The version of the controller used for a human player then looks like:

Collapse
public class HumanPaddleController implements PaddleController {

private boolean leftPressed = false;


private boolean rightPressed = false;

public HumanPaddleController() {
}

public void initialize() {


}

public void updatePaddleData(int x, int y, int width) {


}
public void updateBall(int x, int y, int deltaX, int deltaY) {
}

public void keyPressed(int keyCode, int gameAction) {


switch(gameAction) {
case Canvas.LEFT: leftPressed = true; break;
case Canvas.RIGHT: rightPressed = true; break;
}
}

public void keyReleased(int keyCode, int gameAction) {


switch(gameAction) {
case Canvas.LEFT: leftPressed = false; break;
case Canvas.RIGHT: rightPressed = false; break;
}
}

public int getCommand() {


if (leftPressed)
return PaddleController.COMMAND_MOVE_LEFT;
if (rightPressed)
return PaddleController.COMMAND_MOVE_RIGHT;

return PaddleController.COMMAND_NOTHING;
}
}

The computer controlled version is implemented like this:

Collapse
public class ComputerPaddleController implements PaddleController {

private int width;


private int height;

private int ballX = 0;


private int ballY = 0;
private int ballDeltaX = 0;
private int ballDeltaY = 0;

private int paddleX = 0;


private int paddleY = 0;
private int paddleWidth = 0;

public ComputerPaddleController(int width, int height) {


this.width = width;
this.height = height;
}

public void updatePaddleData(int x, int y, int width) {


paddleX = x;
paddleY = y;
paddleWidth = width;
}
public void updateBall(int x, int y, int deltaX, int deltaY) {
ballX = x;
ballY = y;
ballDeltaX = deltaX;
ballDeltaY = deltaY;
}

public void keyReleased(int keyCode, int gameAction) {


}

public void keyPressed(int keyCode, int gameAction) {


}

public void initialize() {


}

public int getCommand() {


if (ballDeltaY < 0) {
// If ball is moving up, place paddle in center
int targetDifferance = paddleX + (paddleWidth / 2) -
width / 2;
if (Math.abs(targetDifferance) > paddleWidth / 10) {
if (targetDifferance < 0)
return PaddleController.COMMAND_MOVE_RIGHT;
if (targetDifferance > 0)
return PaddleController.COMMAND_MOVE_LEFT;
}
}
else {
// If ball is coming down, move towards it
int targetDifference = paddleX + (paddleWidth / 2) - ballX;
if (Math.abs(targetDifference) > paddleWidth / 12) {
if (targetDifference < 0)
return PaddleController.COMMAND_MOVE_RIGHT;
if (targetDifference > 0)
return PaddleController.COMMAND_MOVE_LEFT;
}
}
return PaddleController.COMMAND_NOTHING;
}
}

One could argue that the key input method's shouldn't really be part of this interface, and
that the HumanPaddleController should read the input in some other way. While that
would make the interface cleaner and a better abstraction of a paddle's controller I've
gone with this approach for simplicity.

A neat thing with abstracting the controller in this way is that it allows for easy
debugging; the computer will always play in exactly the same way (provided that the
starting conditions are the same) and that means that the programmer won't have to play
the game manually to test things like the game over state that kicks in when the game has
been beaten. It's also possible to write a computer controller that plays according to a set
of instructions recorded when a human controller was used, this is a very good thing to
incorporate into simple games as it's convinient way to get back to a state where a bug
was found.
The abstraction also hints at a way of creating a network controller so that multiplayer
games can be created, the network controller would simply connect to a client controller
that would receive the input and provide the commands and it would be transparent to the
implementation that one player is a remote player (not that that example is very
applicable to a break out style game).

Collision Detection
Collision detection is an important part of a lot of different games, wether it is to find out
when a ball hits a paddle or when a character walks into a wall. Depending on the type of
game collision detection can be implemented in different ways, one approach is to check
if two objects has collided, and if they have move them apart. That's the approach I've
gone for in this example, but I've structured it so that from the Ball's point of view, the
movement is altered before the ball is actually inside one of the bricks or the paddle.

Bounding Box

Central to my collision detection is the BoundingBox class, it represents a rectangle on


which collisions can be tested. The concept of a bounding shape is central to a lot of
game collision detection and there are many variations such as bounding sphere, circle
and cylinders.

The BoundingBox contains position and size of the rectangle, and using this information
it's easy to determine if a point lies outside or inside (collision) the box.

Collapse
public class BoundingBox {

...

private int x;
private int y;
private int width;
private int height;

public BoundingBox(int x, int y, int width, int height) {


this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

public boolean isInside(int px, int py) {


if (px < x || px > x + width)
return false;
if (py < y || py > y + height)
return false;
return true;
}

...
}

But just determining if a collision has occured is not enough. In my experience (which
granted is quite limited in this area), it's often easy to figure out if a collision has occured,
what is difficult to compute is the Collision Response and the information required for
that. In this example game, the ball needs to bounce off walls, bricks and the paddle in a
correct way. It won't do to just reverse the direction of the ball because it's always coming
in at an angle. Therefore it's important to calulate which side of the paddle, wall or brick
the ball collided with.

In the case of a simple break out game, the collision response if fairly simple; if the ball
collides with a horizontal edge negate the vertical velocity and vice versa. The problem is
how to figure out with which edge the ball collided. I've used this method:

• 1. Check if the Ball's current position plus it's current velocity would place it
inside a BoundingBox
• 2. If a collision will occur, use the current velocity and position relative to the
BoundingBox's position to figure out which edge the Ball collided with.
• 3. Use the edge information to cap the movement of the Ball so that it only
travels to the edge of the BoundingBox.
• 4. Negate either the vertical or the horizontal velocity depending on the edge
collided with.

I came up with a system of regions, and based on which region the ball is in (the regions
relate to the edges of the BoundingBox) there's only two possible edges that the Ball
could have collided with.

Example
In this example the Ball is in region 8, and is moving with a horizontal velocity of 2
units per second and a vertical velocity of 1 unit per second. The only two edges the Ball
can collide with from region 8 is the bottom and right edge. But because the horizontal
velocity is greater than the vertical the colliding edge will be the bottom one.

It doesn't take a genius to see that this method has it's flaws and will in some cases pick
the wrong edge as the colliding one but it's close enough for this example. (To correct the
method you'd need to extend a vector out from the closes corner in the direction of the
negative velocity of the Ball and then determine which side of that vector that the Ball
is on, I haven't got the energy to implement that in this example though, I'm saving all the
vector maths to part 4 :).

The BoundingBox returns a CollisionInformation object with information about


where on the edge the collision would have occured, this information is then used by the
Ball to adjust it's position and velocity.

Collapse
public class Ball {

...

public int processCollisions(BrickField brickField) {


int numberOfRemovedBricks = 0;

// For each brick in the brick field...


for(int row = 0; row < brickField.getNumberOfRows(); ++row) {
for(int column = 0; column <
brickField.getNumberOfColumns(); ++column) {
Brick brick = brickField.getBrick(row, column);

// If the brick isn't already removed...


if (!brick.isRemoved()) {
BoundingBox brickBoundingBox =
brick.getBoundingBox();

for (int i = 0; i < xOffset.length; ++i) {


int ox = x + xOffset[i];
int oy = y + yOffset[i];

// Check if there will be a collision


BoundingBox.CollisionInfo collisionInfo =
brickBoundingBox.willCollide(ox, oy, deltaX, deltaY);
if (collisionInfo != null) {
// If there is a collision, remove the
brick...
brick.remove();
++numberOfRemovedBricks;

// ...correct the position to the edge of


the brick...
x += collisionInfo.CorrectionOffsetX;
y += collisionInfo.CorrectionOffsetY;
// ...and alter the ball's velocity
depending on the edge collided with.
switch(collisionInfo.Edge) {
case BoundingBox.EDGE_BOTTOM:
case BoundingBox.EDGE_TOP:
deltaY = -deltaY;
break;
case BoundingBox.EDGE_LEFT:
case BoundingBox.EDGE_RIGHT:
deltaX = -deltaX;
}
}
}
}
}
}
return numberOfRemovedBricks;
}

Similar methods are used for the paddle and the walls.

Points of Interest
Generated resources

Graphics

In this example you'll notice that there are no images or sprites included, that's because
all the graphics in this game is generated on the fly. That's easy to do if the game has
simple graphics by using the different draw methods on the Graphics object. The bricks,
ball and paddle are all generated using the current width and height of the screen, that
means that the game will look Ok even if the aspect ractio or screen size changes.

This screen shot shows the game running under emulators with different screen sizes.
Sounds

The sounds in this game are also generated, check out the SoundManager class to see how
you can get the device to play simple notes. That class also knows how to render it's
volume state to the screen similar to what you'd see on the TV screen when changing
volume.

Next Part
In the next part I'll dicuss J2ME's TiledLayer when I demonstrate how to write a top
down scroller. I'll also cover how to load resources such as a game level and continue to
show how to use offsceens, menuscreens and AI controllers.
As always, any comments on the article or the code are most welcome.

License
This article, along with any associated source code and files, is licensed under The Code
Project Open License (CPOL)

You might also like