Creating a game on Google Android game with Flixel – Adding Weapons

Google+ Pinterest LinkedIn Tumblr +

DOWNLOAD THE SOURCE CODE

VIEW THE VIDEO

RETURN TO THE TUTORIAL INDEX

Like the Enemy and Player classes, weapons are simply classes that extend the FlxSprite class. The code in the Bullet class, which represents an individual bullet fired by the player, follows the same logic as the Player and Enemy classes: it calls the underlying FlxSprite constructor and defines some animations. The only difference with the Bullet class is that it sets the exists variable to false. This is done because a collection of bullets will be initially created but left in an inactive state until the player fires one.

You may also note that we have not set up any of the physics variables like velocity in the constructor. Instead the player will set the velocity of the bullet when it is fired, because it is only then that the direction of the bullet will be known.

Bullet.java

package org.myname.flixeldemo;

import java.util.ArrayList;
import java.util.Arrays;

import org.flixel.*;

public class Bullet extends FlxSprite
{
 public Bullet()
 {
  super(0, 0, R.drawable.bullet, true);
  
  exists = false;
  
  addAnimation("up",new ArrayList(
   Arrays.asList(new Integer[] {0})));
  addAnimation("down",new ArrayList(
   Arrays.asList(new Integer[] {1})));
  addAnimation("left",new ArrayList(
   Arrays.asList(new Integer[] {2})));
  addAnimation("right",new ArrayList(
   Arrays.asList(new Integer[] {3})));
  addAnimation("poof",new ArrayList(
   Arrays.asList(new Integer[] {4, 5, 6, 7})), 50, false);
 }

The update function waits until the bullet is dead (i.e. it has collided with an enemy or with the wall) and the current animation has finished, and then sets exists to false to remove it from the game. Otherwise the FlxSprite update function will move the bullet along its path.

 public void update()
 {
  if(dead && finished) exists = false;
  else super.update();
 }

The hitFloor, hitCeiling and hitWall functions are called by the collision system to allow an object the opportunity to ignore a collision from a given direction (say if you wanted a character to be able to jump up through the ground, but then treat the ground as solid when it falls back down onto it). Here we use these functions to call to call the hurt function. Normally this will subtract some life from the object, but in this case we have overridden the function to set the dead variable to true, and play the “poof” animation.

 public boolean hitWall(FlxCore Contact) 
  { hurt(0); return true; }
 public boolean hitFloor(FlxCore Contact) 
  { hurt(0); return true; }
 public boolean hitCeiling(FlxCore Contact) 
  { hurt(0); return true; }
 public void hurt(float Damage)
 {
  if(dead) 
   return;
  velocity.x = 0;
  velocity.y = 0;
  dead = true;
  play("poof");
 }

The shoot function is called by the player to take an inactive bullet (i.e. one where the exists variable is false) and place it back into the game at the specified position and with the specified velocity.

 public void shoot(float bX, float bY, float bXVel, float bYVel)
 {
  super.reset(bX,bY);
  velocity.x = bXVel;
  velocity.y = bYVel;
  if(velocity.y < 0)
   play("up");
  else if(velocity.y > 0)
   play("down");
  else if(velocity.x < 0)
   play("left");
  else if(velocity.x > 0)
   play("right");
 }

}

In the GameState constructor we create eight new Bullet objects, and place them in a new collection called playerBullets. The Player constructor has been modified to accept a reference to this new collection.

If you look closely we have also split the loop that creates the level FlxBlock platforms and the Enemy objects. This is because the order in which these objects are created defines their order on the screen – objects created later appear over the top of those created earlier. By creating the Enemy objects after the FlxBlock objects we ensure that the enemies (and the FlxEmitters that we will add when they die) are drawn on top of the blocks that make up the level.

GameState.java

 public GameState()
 {
  levelBlocks.add(this.add(
   new FlxBlock(0, 640-16, 640, 16)
    .loadGraphic(R.drawable.tech_tiles)));
  levelBlocks.add(this.add(
   new FlxBlock(0, 0, 640, 16)
    .loadGraphic(R.drawable.tech_tiles)));
  levelBlocks.add(this.add(
   new FlxBlock(0, 16, 16, 640-32)
    .loadGraphic(R.drawable.tech_tiles)));
  levelBlocks.add(this.add(
   new FlxBlock(640-16, 16, 16, 640-32)
    .loadGraphic(R.drawable.tech_tiles)));
  
  for (int i = 0; i < 4; ++i)
   levelBlocks.add(this.add(
    new FlxBlock(320 - 48 - 32*i, 640 - 48 - 48*i, 320, 16)
     .loadGraphic(R.drawable.tech_tiles)));
  
  for (int i = 0; i < 4; ++i)
   enemies.add(this.add(
    new Enemy(320 - 48 - 32*i, 640 - 48 - 48*i, 320)));
  
  for (int i = 0; i < 8; ++i)
   playerBullets.add(this.add(new Bullet()));
   
  player = new Player(playerBullets);
  this.add(player);
  FlxG.follow(player, 2.5f);
  FlxG.followAdjust(0.5f, 0.0f);
  FlxG.followBounds(0, 0, 640, 640);
  
  FlxG.playMusic(R.raw.mode);
 }

The update function is modified to include a new collision check between the bullets and the level blocks and the enemies. When a collision is detected with an enemy both the bullet and the enemy have their hurt function called.

 public void update()
 {
  super.update();
  FlxG.collideArrayList(levelBlocks, player);
  FlxG.overlapArrayList(enemies, player, new FlxCollideListener(){
    public void Collide(FlxCore object1, FlxCore object2)
    {
     player.kill();
     FlxG.fade(0xffd8eba2,3, new FlxFadeListener()
      {
       public void fadeComplete()
       {
        FlxG.switchState(MenuState.class);
       }
      }
     );
    }
   }  
  );
  
  FlxG.collideArrayLists(playerBullets, levelBlocks);
  FlxG.overlapArrayLists(playerBullets, enemies, new FlxCollideListener()
   {
    public void Collide(FlxCore bullet, FlxCore enemy)
    {
     ((FlxSprite)bullet).hurt(0);
     ((FlxSprite)enemy).hurt(1);
    }
   }
  );
  
 }

Like the Player class in the last tutorial, the Enemy class now gains a FlxEmitter which is triggered when the enemy dies.

 public Enemy(int x, int y, int maxXMovement)
 {
  super(x, y, R.drawable.enemy, true);
  
  this.y -= this.height;
  this.maxXMovement = maxXMovement - this.width;
  this.startX = x;
  this.velocity.x = VELOCITY;
    
  addAnimation("idle", new ArrayList(Arrays.asList(new Integer[] {0, 1})), 12);
  
  play("idle");
  
  this.gibs = FlxG.state.add(
    new FlxEmitter(0, 0, -1.5f)
     .setXVelocity(-150.0f, 150.0f)
     .setYVelocity(-200.0f, 0.0f)
     .setRotation(-720, 720)
     .setGravity(400)
     .createSprites(R.drawable.enemygibs));
 }

 public void kill()
 {
  super.kill();
  
  this.gibs.x = this.x + (this.width>>1);
  this.gibs.y = this.y + (this.height>>1);
  this.gibs.restart();
 }
Share.

About Author

Leave A Reply