Game initialization occurs by overriding the initialize method in the Asteroids class (see Listing 4-6). It starts by loading sounds from the res/raw folder as follows:
Context ctx = getContext();
crashSound = new AudioClip(ctx, R.raw.a_crash); clipTotal++;
explosionSound = new AudioClip(ctx, R.raw.a_explosion); clipTotal++;
Here is where we use the AudioClip class to quickly load the raw resource using its ID. Note that we also need the application Context. The game also keeps track of the total number of clips in the game.
Next, we create the star background using an array of Points and the size of the screen:
void createStarts() { int width = getWidth(); int height = getHeight();
// Generate the starry background. numStars = width * height / 5000; stars = new Point[numStars];
102
for (i = 0; i < numStars; i++) { // random XY Point
stars[i] = new Point((int) (Math.random() * width) , (int) (Math.random() * height) );
} }
The stars are created using random Points with X and Y coordinates defined using the getWidth and
getHeight methods. Note that getWidth and getHeight are built-in methods provided by the LinerLayout
class.
Next, we create all polygon sprites in the game:
• The ship
• The ship’s thrusters
• Photons (the ship’s bullets)
• The flying saucer
• Asteroids and asteroid explosions
Note that all elements in the game are polygons, even the tiny photons and asteroid explosions. Finally, miscellaneous data is initialized and the game is put in Game Over mode.
Listing 4-6. Game Initialization protected void initialize() { // Load sounds
try {
loadSounds(); loaded = true; } catch (Exception e) {
Tools.MessageBox(mContex, "Sound Error: " + e.toString()); }
// create star background createStarts();
// Create shape for the ship sprite. ship = new PolygonSprite();
ship.shape.addPoint(0, -10); ship.shape.addPoint(7, 10); ship.shape.addPoint(-7, 10); // Create thruster shapes createThrusters();
// Create shape for each photon sprites. for (i = 0; i < Constants.MAX_SHOTS; i++) {
103
photons[i] = new PolygonSprite(); photons[i].shape.addPoint(1, 1); photons[i].shape.addPoint(1, -1); photons[i].shape.addPoint(-1, 1); photons[i].shape.addPoint(-1, -1); }
// Create shape for the flying saucer. ufo = new PolygonSprite();
ufo.shape.addPoint(-15, 0); ufo.shape.addPoint(-10, -5); ufo.shape.addPoint(-5, -5); ufo.shape.addPoint(-5, -8); ufo.shape.addPoint(5, -8); ufo.shape.addPoint(5, -5); ufo.shape.addPoint(10, -5); ufo.shape.addPoint(15, 0); ufo.shape.addPoint(10, 5); ufo.shape.addPoint(-10, 5);
// Create shape for the guided missile. missile = new PolygonSprite();
missile.shape.addPoint(0, -4); missile.shape.addPoint(1, -3); missile.shape.addPoint(1, 3); missile.shape.addPoint(2, 4); missile.shape.addPoint(-2, 4); missile.shape.addPoint(-1, 3); missile.shape.addPoint(-1, -3); // Create asteroid sprites.
for (i = 0; i < Constants.MAX_ROCKS; i++) asteroids[i] = new PolygonSprite(); // Create explosion sprites.
for (i = 0; i < Constants.MAX_SCRAP; i++) explosions[i] = new PolygonSprite();
// Initialize game data and put it in 'game over' mode. highScore = 0; sound = true; detail = true; initGame(); endGame(); }
Drawing Sprites
Drawing 23.70the sprites is the next step in the game life cycle and the most important too. Here is where all polygon sprites are drawn (see Listing 4-7). The most important steps are as follows:
104
1. The size of the screen is queried using the layout’s getWidth and getHeight
methods. The size is required to render elements on screen
2. The stars are drawn using an array of star sprites and calling canvas.drawPoint. Each sprite is drawn using its X and Y coordinates and a Paint object for style information.
3. Photons are drawn only if they are active. A photon becomes active when the user presses the space bar to fire the gun. Each photon is aware of its position on the canvas.
4. Missiles, a UFO, and the user’s ship are drawn if they are active. When the user reaches a score threshold, the UFO will show up. Users must watch out for the missiles fired against them by the UFO. Note that the ship’s thrusters must be drawn when the user presses the arrow keys to move the ship around.
5. Asteroids and explosion debris are drawn. Note that each bit of debris is an independent sprite.
6. Status messages are drawn. Messages include the score in the upper-left corner, the number of ships left in the lower-left, and the high score in the upper-right.
7. Other messages are displayed depending on the state of the game, including Game Over, Game Paused, or Sound Muted.
■Tip Remember that each sprite is aware of its X and Y coordinates on screen and angle of rotation? The key
method that performs all the magic is
PolygonSprite.draw(Canvas canvas, Paint paint). Within this method,
the polygon lines are drawn using
canvas.drawLines(float[] points, Paint paint).
Listing 4-7. The Drawing Subroutine for Asteroids protected void onDraw(Canvas canvas) {
// get screen size int width = getWidth(); int height = getHeight(); // draw stars
for (i = 0; i < numStars; i++) {
canvas.drawPoint(stars[i].x, stars[i].y, mPaint); }
// Draw photon bullets.
for (i = 0; i < Constants.MAX_SHOTS; i++) { if (photons[i].active) {
105
} }
// Draw the guided missile, if (missile.active) {
missile.draw(canvas, mPaint); }
// Draw the flying saucer. if (ufo.active) {
ufo.draw(canvas, mRedPaint); }
// Draw the ship if (ship.active) { // draw ship
ship.draw(canvas, mPaint);
// Draw thruster exhaust if thrusters are on. Do it randomly to get // a flicker effect.
if (!paused && Math.random() < 0.5) { if (up) { fwdThruster.draw(canvas, mPaint); } if (down) { revThruster.draw(canvas, mPaint); } } }
// Draw the asteroids.
for (i = 0; i < Constants.MAX_ROCKS; i++) { if (asteroids[i].active) {
asteroids[i].draw(canvas, mGreenPaint); }
}
// Draw any explosion debris.
for (i = 0; i < Constants.MAX_SCRAP; i++) { if (explosions[i].active) {
explosions[i].draw(canvas, mGreenPaint); }
}
// Display status messages.
float fontSize = mPaint.getTextSize(); // upper left
canvas.drawText("Score: " + score, fontSize, mPaint.getTextSize(), mPaint);
106
// Lower Left
canvas.drawText("Ships: " + shipsLeft, fontSize, height - fontSize, mPaint);
// Upper right
String str = "High: " + highScore;
canvas.drawText("High: " + highScore, width
- (fontSize / 1.2f * str.length()), fontSize, mPaint); if (!sound) {
str = "Mute";
canvas.drawText(str, width - (fontSize * str.length()), height - fontSize, mPaint);
}
if ( ! playing) { if (loaded) {
str = "Game Over";
final float x = (width - (str.length() * fontSize / 2)) / 2; canvas.drawText(str, x, height / 4, mPaint);
} }
else if ( paused ) { str = "Game Paused";
final float x = (width - (str.length() * fontSize / 2)) / 2; canvas.drawText(str, x, height / 4, mPaint);
} }