You are here

Chapter 26: Add some firepower

The last, but not least, of our moving objects is the missile (or the "missiles", as there can be quite many of them at the same time).

I choose to implement these missiles similar to the asteroids, with a Missile object, a MissileHandler containing a list of all active missiles and so on.

So let's begin with Missile.java:

package com.ajomannen.justroids;

import android.graphics.Bitmap;

public class Missile extends GfxObject {
  public long age;

  public Missile(Bitmap bitmap, float x, float y, double velocity,
    double direction) {
   age = 0;
   this.bitmap = bitmap;
   this.x = x;
   this.y = y;
   setVelocity(velocity);
   setDirection(direction);
  }

}

Notice that we included the member variable "age" here. Remember that a missile only should live a limited amount of time? That's were "age" comes in.

The MissileHandler is also pretty straight-forward:

package com.ajomannen.justroids;

import java.util.ArrayList;
import java.util.List;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;

public class MissileHandler {
  private Bitmap bitmap;
  public List<Missile> missiles;
  private Paint paint;

  public MissileHandler(Resources resources) {
   paint = new Paint();
   bitmap = BitmapFactory.decodeResource(resources, R.drawable.missile_20);
   missiles = new ArrayList<Missile>();
  }

  public void update(float screenWidth, float screenHeight, int pendingEvent,
    float shipX, float shipY, int shipAngle) {
   if (pendingEvent == GameEngine.EVENT_FIRE) {
    Missile newMissile = new Missile(bitmap, shipX, shipY, 3, shipAngle);
    missiles.add(newMissile);
   }
   for (Missile missile : missiles) {
    missile.age++;
    missile.move(screenWidth, screenHeight);
   }
  }

  public void draw(Canvas canvas) {
   for (Missile missile : missiles) {
    missile.draw(canvas, missile.x, missile.y, paint);
   }
  }

}

One big difference compared to the AsteroidHandler is that we do not create any missiles at all when the handler is created. A second difference is that we pass on any pending event plus the position and angle of the ship during each update, so that we can create new missiles in the right place.

In the GameEngine, we simply introduce MissileHandler in the same way as AsteroidHandler:

package com.ajomannen.justroids;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;

public class GameEngine {

  Context context;
  Resources resources;

  public float screenWidth;
  public float screenHeight;
  private Paint blackPaint;

  private int level;
  private AsteroidHandler asteroidHandler;
  private MissileHandler missileHandler;
  private Ship ship;

  public static final int EVENT_NONE = 0;
  public static final int EVENT_LEFT = 1;
  public static final int EVENT_RIGHT = 2;
  public static final int EVENT_THRUST = 3;
  public static final int EVENT_FIRE = 4;
  public int pendingEvent = EVENT_NONE;

  public void Init(Context context) {
   this.context = context;
   resources = context.getResources();

   blackPaint = new Paint();
   blackPaint.setColor(Color.BLACK);
   blackPaint.setStyle(Style.FILL);

   level = 5;
   asteroidHandler = new AsteroidHandler(resources, level);
   missileHandler = new MissileHandler(resources);
   ship = new Ship(resources, 120, 280, 0.1, 0, 0);

   setSurfaceDimensions(240, 320);

  }

  public void onDestroy() {
   try {
   } catch (Exception e) {
   }
  }

  public void setSurfaceDimensions(int width, int height) {
   screenWidth = width;
   screenHeight = height;
  }

  public void update() {
   asteroidHandler.update(screenWidth, screenHeight);
   ship.update(screenWidth, screenHeight, asteroidHandler.asteroids,
     pendingEvent);
   missileHandler.update(screenWidth, screenHeight, pendingEvent, ship.x,
     ship.y, ship.angle);
   pendingEvent = EVENT_NONE;
  }

  public void draw(Canvas canvas) {
   canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), blackPaint);
   asteroidHandler.draw(canvas);
   ship.draw(canvas);
   missileHandler.draw(canvas);
  }

}

The last change we have to make, in order to be able to fire away those missile, is to open up GameSurface and replace the line:

Log.d("JustRoids", "MotionEvent: Tap (Fire)");

with:

gameEngine.pendingEvent = GameEngine.EVENT_FIRE;

There's still some work to do in order to make the missiles "die" when they're too old and to make them split the asteroids in two when they hit them, but let's run our app again and fire off a bunch of missiles in different directions too see how it looks:

 

That's all for now!

Next chapter will cover the work that's left, as mentioned above.

 

Requirements implemented in this chapter

✔ 17. The ship fires missiles when you "tap" on the screen.

✔ 21. Objects (asteroids, missiles, ship) shall "loop" over the screen's edges and re-appear on the other side.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer