Creating a Flash platform game with Flixel and Flex – Powerup Blocks

Google+ Pinterest LinkedIn Tumblr +

VIEW THE DEMO

DOWNLOAD THE SOURCE CODE

RETURN TO THE TUTORIAL INDEX

Powerup blocks were common in a lot of old school platform games like Mario. These are the blocks that drop a power up, coin or something else when the player jumps into it. This kind of block can be recreated fairly easily with Flixel.

 public class PowerupBlock extends FlxBlock
{

We create a new class called PowerupBlock, which extends the FlxBlock class.

  protected static const BOUNCE_HEIGHT:Number = 3;
protected static const BOUNCE_COUNT:int = 5;
protected static const BOUNCE_TIME:Number = 0.5;

When the player jumps into the block it will bounce up and down. These constants define what this bouncing will look like.

The BOUNCE_HEIGHT constant defines how far in the y axis the block will move when it is bouncing.

The BOUNCE_COUNT constant defines how many times the block will bounce.

The BOUNCE_TIME constant defines how long the block will bounce for.

  protected var bounceTime:Number = -1;
protected var dropped:Boolean = false;
protected var dropFunction:Function = null;

The bounceTime variable is used to keep a track of how long the block has been bouncing for when it has been hit. A value of -1 means that it is not bouncing.

The dropped variable indicates if the block has dropped its power up.

The dropFunction points to a function that will be called when the block is hit. It is in this function that the power up will be dropped.

  public function PowerupBlock(dropFunction:Function, X:int, Y:int, Width:uint, Height:uint, TileGraphic:Class, Empties:uint=0)
{
super(X, Y, Width, Height, TileGraphic, Empties);
this.dropFunction = dropFunction;
}

The constructor initialises the underlying FlxBlock class, and sets the dropFunction variable.

  override public function collide(Core:FlxCore):void
  {   
   //Basic overlap check
   if( (Core.x + Core.width <= this.x) ||
    (Core.x >= this.x + this.width) ||
    (Core.y >= this.y + this.height) ||
    (Core.y + Core.height <= this.y))
    return;
    
   // check to see from what direction we moved into the block
   var contactFromLeft:Boolean = Core.x + Core.width > this.x &&
    Core.last.x + Core.width <= this.last.x;    
   var contactFromRight:Boolean = Core.x < this.x + this.width &&
    Core.last.x >= this.last.x + this.width;    
   var contactFromBottom:Boolean = Core.y < this.y + this.height &&
    Core.last.y >= this.last.y + this.height;
   var contactFromTop:Boolean = Core.y + Core.height > this.y &&
    Core.last.y + Core.height <= this.last.y;
   
   if (contactFromLeft && Core.hitWall(this))
   {
    Core.x = this.x - Core.width;
   }
   
   if (contactFromRight && Core.hitWall(this))
   {
    Core.x = this.x + this.width; 
   }
   
   if (contactFromBottom && Core.hitCeiling(this))
   {
    Core.y = this.y + this.height;
    if (!dropped)
    {
     bounceTime = BOUNCE_TIME;
     dropped = true;
     if (dropFunction != null)
      dropFunction(this);
    }
   }
   
   if (contactFromTop && Core.hitFloor(this) )
   {
    Core.y = this.y - Core.height;
   }
  }
  
  public override function update():void
  {
   super.update();
   if (bounceTime != -1)
   {
    bounceTime -= FlxG.elapsed;
    if (bounceTime <= 0)
    {
     bounceTime = -1;
    }
   }
  }

Just like the BounceBlock, the collision function has been overridden. In here we push the player out of the block, just like the FlxBlock would. We also detect when the block has been hit from underneath, in which case we initiate the bouncing and call the function referenced by dropFunction.

  protected override function getScreenXY(P:Point):void
  {
   super.getScreenXY(P);
   if (bounceTime != -1)
    P.y += Math.sin(bounceTime / BOUNCE_TIME * Math.PI * BOUNCE_COUNT) * BOUNCE_HEIGHT;
  }
 }

The blocks bouncing should not affect how it interacts with game objects – i.e. when it is bouncing it should collide like it is not moving. The easiest way to make this block appear to bounce, but not to change the internal variables that affect the collision code, is to override the getScreenXY function. This function translates the objects world position (the x and y) into a position on the screen. Here, if the block is bouncing, we adjust the y value so it will follow a sine wave, making it appear to move up and down. Since we have not modified the x and y values for the block itself, it will still collide as if it were not moving.

  protected var powerupBlocks:FlxArray = new FlxArray(); 
  public function GameState()
  {
   // ...
   
   powerupBlocks.add(
    this.add(
     new PowerupBlock(
      dropCoin,
      LEVEL_DIMENSIONS>>1,
      LEVEL_DIMENSIONS - BLOCK_DIMENSIONS * 4,
      BLOCK_DIMENSIONS,
      BLOCK_DIMENSIONS,
      PowerupBlockImage
     )
    )
   );
   
   // ...
  }

The GameState gains a new FlxArray to hold the powerup blocks. We also add a powerup block to the this collection in much the same way that we add static blocks. The only difference is that we pass in the new dropCoin function to the PowerupBlcok, which will be called when the player jumps into the block.

  public override function update():void
  {
   super.update();
   
   FlxG.collideArray(movingBlocks, player);
   FlxG.collideArray(powerupBlocks, player);   
   FlxG.collideArray(levelBlocks, player);
   FlxG.collideArrays(playerBullets, levelBlocks);
   FlxG.collideArrays(playerBullets, powerupBlocks);  
   
   FlxG.collideArrays(movingBlocks, coins);  
   FlxG.collideArrays(levelBlocks, coins);  
   
   FlxG.overlapArray(coins, player, coinPickup);
   
   FlxG.overlapArray(movingBlocks, player, playerSquash);
   FlxG.overlapArray(levelBlocks, player, playerSquash);    
  }

The collision detection code is modified slightly so the player will collide with the powerup blocks, but the coins don’t. This means that when we drop a coin from the powerup block it will fall right through it.

  protected function dropCoin(block:FlxBlock):void
  {
   coins.add(
    this.add(new Coin(CoinsImage, block.x, block.y)));
  }

The dropCoin function simply creates a new coin at the location of the powerup block.

  public function Coin(Graphic:Class=null, X:int=0, Y:int=0)
  {
   super(Graphic, X, Y, true);
   this.y -= this.height;
   this.addAnimation("spin", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10);
   this.play("spin");
   
   this.acceleration.y = GRAVITY_ACCELERATION;
  }

The Coin class also has to be modified to add some gravity. This way the coins created by the GameState dropCoin function will drop down to the ground beneath.

Share.

About Author

Leave A Reply