The Invader Class

Invaders are just floating in space according to a predefined pattern. Figure 12-11 shows you this pattern.

Figure 12-11. Movement of the invaders. Left, down, right, down, left, down, right, down...

An invader follows an extremely simplistic movement pattern. From its initial position it first moves to the right for some distance. Next it moves downward (which means in the direction of the positive z-axis on our playing field), again for a specified distance. Once done with that it will start moving to the right, basically backtracking to the same x-coordinate it was before it started moving left.

The left and right movement distances are always the same, except in the beginning. Figure 12-11 illustrates the movement of the top-left invader. Its first left movement is shorter than all subsequent movements to the left or right. The horizontal movement distance is half the playing field width, 14 units in our case. For the first horizontal movement the distance an invader has to travel is half of that, 7 units.

What we have to do is keep track of the direction an invader is moving in and how far he has moved in that direction already. If he reaches the movement distance for the given movement state (14 units for horizontal movement, 1 unit for vertical movement) it switches to the next movement state. All invaders will have their movement distance set to half the playing field's width initially. Look again at Figure 12-11 to make sure why that works! This will make the invaders sort of bounce off the edges of the playing field to the left and right.

Invaders also have a constant velocity. Well, actually the velocity will increase each time we generate a new wave of invaders in case all invaders of the current wave are dead. We can achieve this by simply multiplying this default velocity by some constant which is set from outside, namely the World class responsible for updating all invaders.

Finally, we also have to keep track of the state of the invader, which can again be either alive or exploding. We'll use the same mechanism as in case of the ship, with a state and a state time. Listing 12-9 shows you the code.

Listing 12-9. Invader.java, the Invader Class package com.badlogic.androidgames.droidinvaders;

import com.badlogic.androidgames.framework.DynamicGameObject3D;

public class Invader extends DynamicGameObject3D { static final int INVADER_ALIVE = 0; static final int INVADER_DEAD = 1; static final float INVADER_EXPLOSION_TIME = 1.6f; static final float INVADER_RADIUS = 0.75f; static final float INVADER_VELOCITY = 1; static final int MOVE_LEFT = 0; static final int MOVE_DOWN = 1; static final int MOVE_RIGHT = 2;

We start with some constants, defining the state of an invader, the duration of its explosion, its radius and default velocity, as well as three constants that allow us to keep track of what direction the invader is currently moving in.

int state = INVADER_ALIVE;

float stateTime = 0;

int move = MOVE_LEFT;

boolean wasLastStateLeft = true;

float movedDistance = World.WORLD_MAX_X / 2;

We keep track of an invader's state, state time, movement direction, and movement distance, which we set to half the playing field width initially. We also keep track of whether the last horizontal movement was to the left or not. This allows us to decide which direction the invader should go once it has finished its vertical movement on the z-axis.

public Invader(float x, float y, float z) { super(x, y, z, INVADER_RADIUS);

The constructor just performs the usual setup of the invader's position and bounding ship via the super class constructor.

public void update(float deltaTime, float speedMultiplier) { if (state == INVADER_ALIVE) {

movedDistance += deltaTime * INVADER_VELOCITY * speedMultiplier; if (move == MOVE_LEFT) {

position.x -= deltaTime * INVADER_VELOCITY * speedMultiplier; if (movedDistance > World.WORLD_MAX_X) { move = MOVE_DOWN; movedDistance = 0; wasLastStateLeft = true;

position.x += deltaTime * INVADER_VELOCITY * speedMultiplier; if (movedDistance > World.WORLD_MAX_X) { move = MOVE_DOWN; movedDistance = 0; wasLastStateLeft = false;

position.z += deltaTime * INVADER_VELOCITY * speedMultiplier; if (movedDistance > 1) { if (wasLastStateLeft) move = MOVE_RIGHT;

else move = MOVE_LEFT; movedDistance = 0;

bounds.center.set(position);

stateTime += deltaTime;

The update() method takes the current delta time and speed multiplier used to make new waves of invaders move faster. We only perform the movement if the invader is alive, of course.

We start off by calculating how many units the invader will travel in this update and increase the movedDistance member accordingly. If it moves to the left we update the position directly by subtracting the movement velocity to the x-coordinate of the position multiplied by the delta time and speed multiplier. If it has moved far enough we tell it to start moving vertically, by setting the move member to MOVE_DOWN. We also set the wasLastStateLeft to true so that we know that after the down movement is finished we have to move to the right.

We do exactly the same for handling movement to the right. The only difference is that we subtract the movement velocity from the position's x-coordinate and set the wasLastStateLeft to false once the movement distance has been reached.

If we move downward we manipulate the z-coordinate of the invader's position and again check how far we've been moving in that direction. If we reached the movement distance for downward movement we switch the movement state to either MOVE_LEFT or MOVE_RIGHT depending on the last horizontal movement direction encoded in wasLastStateLeft member. Once we are done updating the invaders position we can set the position of the bounding sphere, as we did for the ship. Finally we update the current state time and consider the update to be done.

public void kill() {

state = INVADER_DEAD; stateTime = 0;

The kill() method serves the same purpose as the kill() method of the Ship class. It allows us to tell the invader that it should start dying now. All we do is set its state to INVADER_DEAD and reset its state time. The invader will then not move anymore but only update its state time based on the current delta time.

0 0

Post a comment