Putting everything together

We just need to tie up a few loose ends and we will at last be able to run the game.

Updating GameEngine

Add an instance of the Level class to GameEngine.

...
HUD mHUD;
Renderer mRenderer;
ParticleSystem mParticleSystem;
PhysicsEngine mPhysicsEngine;
Level mLevel;

Initialize the instance of Level in the GameEngine constructor.

public GameEngine(Context context, Point size) {
   super(context);

   mUIController = new UIController(this, size);
   mGameState = new GameState(this, context);
   mSoundEngine = new SoundEngine(context);
   mHUD = new HUD(size);
   mRenderer = new Renderer(this);
   mPhysicsEngine = new PhysicsEngine();

   mParticleSystem = new ParticleSystem();
   mParticleSystem.init(1000);

   mLevel = new Level(context,
                new PointF(size.x, size.y), this);
}

Now we can add some code to the deSpawnRespawn method that we coded the signature for in chapter 18. Remember that this method is called by the GameState class when a new game is needed to start. Add the highlighted code:

public void deSpawnReSpawn() {
    // Eventually this will despawn
    // and then respawn all the game objects

   ArrayList<GameObject> objects = mLevel.getGameObjects();

   for(GameObject o : objects){
       o.setInactive();
   }
   objects.get(Level.PLAYER_INDEX)
          .spawn(objects.get(Level.PLAYER_INDEX)
          .getTransform());
      
   objects.get(Level.BACKGROUND_INDEX)
          .spawn(objects.get(Level.PLAYER_INDEX)
          .getTransform());
      
   
}

The code creates a new ArrayList called objects and initializes it by calling getGameObjects on the instance of Level. A for loop goes through each of the GameObject instances and sets them to an inactive status.

Next, we call spawn on the player and then we call spawn on the background. We use the public static final variables from the Level class to make sure we are using the correct index.

Now we can code the body of the method we added for spawning the player's lasers interface method contents.

public boolean spawnPlayerLaser(Transform transform) {
   ArrayList<GameObject> objects = mLevel.getGameObjects();
   
   if (objects.get(Level.mNextPlayerLaser)
          .spawn(transform)) {
      
          Level.mNextPlayerLaser++;
          mSoundEngine.playShoot();
          if (Level.mNextPlayerLaser == 
                Level.LAST_PLAYER_LASER + 1) {
         
              // Just used the last laser
              Level.mNextPlayerLaser = Level.FIRST_PLAYER_LASER;

      }
   }
   return true;
}

The spawnPlayerLaser method creates and initializes a reference to the ArrayList of GameObject instances by calling getGameObjects.

The code then attempts to spawn a laser from objects at the Level.mNextPlayerLaser index. If it is successful Level.mNextPlayerLaser is incremented ready for the next shot and a sound effect is played using the SoundEngine class.

Finally, there is a nested if which checks if the LAST_PLAYER_LASER was used and if it was sets mNextPlayerLaser back to FIRST_PLAYER_LASER.

Now, update the run method to get all the game objects from the Level class and pass them first into the PhysicsEngine and then the Renderer. The new and altered lines are highlighted.

@Override
public void run() {
   while (mGameState.getThreadRunning()) {
             long frameStartTime = System.currentTimeMillis();
             ArrayList<GameObject> objects = mLevel.getGameObjects();
      
             if (!mGameState.getPaused()) {
                    // Update all the game objects here
                    // in a new way

                // This call to update will evolve 
                // with the project
                if(mPhysicsEngine.update(mFPS,objects, mGameState, 
                      mSoundEngine, mParticleSystem)){
            
                      // Player hit
                      deSpawnReSpawn();
                }
      }

      // Draw all the game objects here
      // in a new way
      mRenderer.draw(objects, mGameState, mHUD, 
            mParticleSystem);

      // Measure the frames per second in the usual way
      long timeThisFrame = System.currentTimeMillis()
                   - frameStartTime;
      if (timeThisFrame >= 1) {
            final int MILLIS_IN_SECOND = 1000;
            mFPS = MILLIS_IN_SECOND / timeThisFrame;
      }
   }
}

This new code will have errors until we update the PhysicsEngine and Renderer next.

Updating PhysicsEngine

Update the update method with the new and altered highlighted lines of code.

// This signature and much more will change later in the project
boolean update(long fps, ArrayList<GameObject> objects, 
                    GameState gs, SoundEngine se, 
                    ParticleSystem ps){

   // Update all the GameObjects
   for (GameObject object : objects) {
          if (object.checkActive()) {
                object.update(fps, objects.get(Level.PLAYER_INDEX)
                   .getTransform());
      }
   }
   
   if(ps.mIsRunning){
      ps.update(fps);
   }

   return false;
}

The first change is with the method signature to accept an ArrayList of GameObject instances. The next change is an enhanced for loop that goes through each of the items in the objects ArrayList, checks if it is active and if it is calls its update method.

At this point all the objects are being updated each frame. We just need to be able to see them.

Updating Renderer

Update the draw method in GameEngine with the new and modified lines which are highlighted next.

void draw(ArrayList<GameObject> objects, GameState gs, HUD hud, ParticleSystem ps) {
   if (mSurfaceHolder.getSurface().isValid()) {
         mCanvas = mSurfaceHolder.lockCanvas();
         mCanvas.drawColor(Color.argb(255, 0, 0, 0));

      if (gs.getDrawing()) {
             // Draw all the game objects here
             for (GameObject object : objects) {
                    if(object.checkActive()) {
                          object.draw(mCanvas, mPaint);
                    }
             }
      }

      if(gs.getGameOver()) {
            // Draw a background graphic here
            objects.get(Level.BACKGROUND_INDEX)
                   .draw(mCanvas, mPaint);
      }

      // Draw a particle system explosion here
      if(ps.mIsRunning){
            ps.draw(mCanvas, mPaint);
      }

      // Now we draw the HUD on top of everything else
      hud.draw(mCanvas, mPaint, gs);

      mSurfaceHolder.unlockCanvasAndPost(mCanvas);
   }
}

First, we updated the method signature to receive the ArrayList with all the objects in. Next there is an enhanced for loop that takes each object in turn, checks if it is active and if it is calls its draw method. The final minor change adds a line of code to the if(gs.getGameOver) block to draw the background (only) when the game is paused.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.155.49