Flixel 2 Tutorial Extended

Published on August 9, 2010

Flixel 2.35 was used in the creation of this tutorial. Written by Adam Saltsman, it was extracted from a couple of his own flash games, such as Canabalt. Flixel is an Actionscript 3 library and as such, you don’t need the Adobe Flash IDE at all. Go to http://www.flashgamedojo.com/go/ to read up on how to get started if you haven’t already.

This tutorial is a continuation of the very excellent tutorial written by Andreas Zecher and can be found at http://www.creativeapplications.net/flash/flixel-2-tutorial-flash-tutorials-games/. If you have not done his tutorial, I highly recommend it. In this tutorial, I’ll explain how I went about adding a little Gradius flavor in the form of extra weapons and powerups.

You can find the complete source code for this tutorial on GitHub including the graphic and sound assets used for the tutorial.

The first thing you’re going to want to do is open up your PlayState.as class. We’re going to declare a few variables related to our powerups.

private var _powerupDropRate:Number = 20; // Specifies the number of enemies to kill to spawn a powerup
private var _powerupDropCounter:Number = 0; // Keeps track of the number of enemies killed to spawn a powerup
public static var _powerupOneCounter:Number = 1; // Keeps track of how many RED powerups the player has; starts the game with level 1 of this weapon
public static var _powerupTwoCounter:Number = 0; // Keeps track of how many GREEN powerups the player has
public static var _powerupThreeCounter:Number = 0; // Keeps track of how many BLUE powerups the player has
private var _powerups:FlxGroup; // Defines the powerup group

Next, add the code to create the group for the powerups in the constructor of PlayState.

_powerups = new FlxGroup; // Creates a new group for the powerups
add(_powerups);

Creating the Powerups

We’re going to create another class called Powerup.as in src/de/pixelate/flixelprimer that will randomly create one of three powerups when called. It will also kill any powerup that leaves the screen without being collected so it doesn’t continue to be updated. (Note: It will still stay in memory. Garbage collection is another lesson for another day)

package de.pixelate.flixelprimer
{
import org.flixel.*;

public class Powerup extends FlxSprite
{
private var randomPowerup:int; // Holds the randomly generated integer used to determine which type of powerup spawns
public var randomPowerupTag:String; // Holds the string used to tell PlayState what powerup to award when picked up

public function Powerup(x:Number,y:Number): void
{

randomPowerup = FlxU.random() * 3; // Generates a random integer 0-2

super(x, y);

if (randomPowerup == 0) // If randomPowerup is equal to 0, create the RED powerup
{
createGraphic(10, 10, 0xFFFF0000);
velocity.x = -150;
randomPowerupTag = "PowerupOne";
}

if (randomPowerup == 1) // If randomPowerup is equal to 1, create the GREEN powerup
{
createGraphic(10, 10, 0xFF00FF00);
velocity.x = -150;
randomPowerupTag = "PowerupTwo";
}

if (randomPowerup == 2) // If randomPowerup is equal to 2, create the BLUE powerup
{
createGraphic(10, 10, 0xFF0000FF);
velocity.x = -150;
randomPowerupTag = "PowerupThree";
}

}

override public function update():void
{
if (x < (FlxG.width - FlxG.width) - 50)
{
kill(); // Kills the powerup if it is not collected and moves off the screen
}

super.update();
}

}

}

When we create our powerups, we need to know where we want to spawn them. Open up your Alien.as class and add the following function.


public function getPowerupSpawnPosition():FlxPoint
{
var powerupPos: FlxPoint = new FlxPoint(x, y); // Gets the position of the alien so a powerup can spawn there
return powerupPos; // Returns the positional value so it can be used
}

Go back to your PlayState class and add the following function that will handle the spawning of the powerups using the position from the previous bit of code added to the Alien class.

private function spawnPowerup(powerupPos: FlxPoint):void
{
var powerup: Powerup = new Powerup(powerupPos.x, powerupPos.y); // Creates a new powerup
_powerups.add(powerup); // Adds the powerup to the powerup group
}

Now, if we want our powerups to actually spawn as enemies are killed, we need to find the overlapAlienBullet function in our PlayState class and add the follow code.

_powerupDropCounter += 1; // Adds 1 to the powerup spawn counter

if (_powerupDropCounter >= _powerupDropRate) // If the powerup kill counter reaches the ceiling...
{
spawnPowerup(alien.getPowerupSpawnPosition()); // Spawns a powerup at the destroyed alien's position
_powerupDropCounter = 0; // Resets the nunber of killed enemies to obtain a powerup to 0
}

Collecting the Powerups

Cool, now our powerups will spawn every 20 kills and slowly move to the left until leaving the screen. Wait! Aren’t we suppose to be able to pick these up? Of course! Open up your PlayState class and add the following function somewhere near the other collision functions.


private function overlapShipPowerup(ship:Ship, powerup:Powerup):void
{
if (powerup.randomPowerupTag == "PowerupOne") // If picking up a RED powerup...
{
_powerupOneCounter += 1; // Increases the strength of the RED powerup if the player already has it
_powerupTwoCounter = 0; // Resets the power of the other weapons
_powerupThreeCounter = 0;

if (_powerupOneCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupOneCounter = 3;
}
}

if (powerup.randomPowerupTag == "PowerupTwo") // If picking up a GREEN powerup...
{
_powerupOneCounter = 0; // Resets the power of the other weapons
_powerupTwoCounter += 1; // Increases the strength of the GREEN powerup if the player already has it
_powerupThreeCounter = 0;

if (_powerupTwoCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupTwoCounter = 3;
}
}

if (powerup.randomPowerupTag == "PowerupThree") // If picking up a BLUE powerup...
{
_powerupOneCounter = 0; // Resets the power of the other weapons
_powerupTwoCounter = 0;
_powerupThreeCounter += 1; // Increases the strength of the BLUE powerup if the player already has it

if (_powerupThreeCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupThreeCounter = 3;
}
}

powerup.kill(); // Removes the powerup when it's collected
}

And then, go to your update() function in Playstate and add:

FlxU.overlap(_ship, _powerups, overlapShipPowerup); // Collision between the player and a powerup

Now you will be able to pickup the powerups by touching them… but it looks like they don’t do anything yet. Time to add it!

Adding the Weapons

Open up your Bullet.as class. We need to make some major changes and addition in order for each different powerup to give the right weapon type.

</pre>
package de.pixelate.flixelprimer
{
import flash.geom.Point;
import org.flixel.*;

public class Bullet extends FlxSprite
{

private var isWeaponTwo:Boolean; // Used to make sure the wave effect is only applied to weapon two shots

public function Bullet(x:Number,y:Number):void
{

super(x, y);

if (PlayState._powerupOneCounter >= 1) // If the player has a RED weapon...
{
createGraphic(16, 4, 0xFF597137);
velocity.x = 1000;
}

if (PlayState._powerupTwoCounter >= 1) // If the player has a GREEN weapon...
{
createGraphic(4, 4, 0xFF597137);
velocity.x = 500;
isWeaponTwo = true; // Lets the update function apply the wave function to these shots
}

if (PlayState._powerupThreeCounter >= 1) // If the player has a BLUE weapon...
{

var shotdirection:Point;
shotdirection = Point.polar(700, ((FlxU.random() * 70) - 35) * 0.017453); // Fires shots in a randomized pattern between -35 and 35 degrees expressed as radians
velocity.x = shotdirection.x;
velocity.y = shotdirection.y;

createGraphic(6, 6, 0xFF597137);
}

}

override public function update():void
{
if (isWeaponTwo == true) // If the player has a GREEN weapon...
{
velocity.y = Math.cos(x / FlxU.random() * 50) * 300; // Moves the shots in a randomized wave pattern
}

if (x > FlxG.width + 50)
{
kill(); // Kills the bullet if it doesn't collide with an enemy before leaving the screen
}

super.update();
}
}

}

Now the game know what weapon type to create when the player has a particular powerup, but they can’t fire them yet. Go back to your PlayState class and find the spawnBullet function and change it to look like this.


private function spawnBullet(p: FlxPoint):void
{
if (_powerupOneCounter == 1) // If the player has RED powerup level 1...
{
var bullet: Bullet = new Bullet(p.x, p.y); // Creates new bullet(s)
_bullets.add(bullet); // Adds them to the bullet group
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupOneCounter == 2) // If the player has RED powerup level 2...
{
var bulletOne: Bullet = new Bullet(p.x, p.y + 7); // Creates new bullet(s)
var bulletTwo: Bullet = new Bullet(p.x, p.y - 7);
_bullets.add(bulletOne); // Adds them to the bullet group
_bullets.add(bulletTwo);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupOneCounter == 3) // If the player has RED powerup level 3...
{
var bulletThree: Bullet = new Bullet(p.x, p.y + 10); // Creates new bullet(s)
var bulletFour: Bullet = new Bullet(p.x, p.y);
var bulletFive: Bullet = new Bullet(p.x, p.y - 10);
_bullets.add(bulletThree); // Adds them to the bullet group
_bullets.add(bulletFour);
_bullets.add(bulletFive);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupTwoCounter == 1) // If the player has GREEN powerup level 1...
{
var bullet2: Bullet = new Bullet(p.x, p.y + 10); // Creates new bullet(s)
var bullet2Two: Bullet = new Bullet(p.x, p.y - 10);
_bullets.add(bullet2); // Adds them to the bullet group
_bullets.add(bullet2Two);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupTwoCounter == 2) // If the player has GREEN powerup level 2...
{
var bullet2Three: Bullet = new Bullet(p.x, p.y + 15); // Creates new bullet(s)
var bullet2Four: Bullet = new Bullet(p.x, p.y);
var bullet2Five: Bullet = new Bullet(p.x, p.y - 15);
_bullets.add(bullet2Three); // Adds them to the bullet group
_bullets.add(bullet2Four);
_bullets.add(bullet2Five);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupTwoCounter == 3) // If the player has GREEN powerup level 3...
{
var bullet2Six: Bullet = new Bullet(p.x, p.y + 20); // Creates new bullet(s)
var bullet2Seven: Bullet = new Bullet(p.x, p.y + 10);
var bullet2Eight: Bullet = new Bullet(p.x, p.y - 10);
var bullet2Nine: Bullet = new Bullet(p.x, p.y - 20);
_bullets.add(bullet2Six); // Adds them to the bullet group
_bullets.add(bullet2Seven);
_bullets.add(bullet2Eight);
_bullets.add(bullet2Nine);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupThreeCounter == 1) // If the player has BLUE powerup level 1...
{
var bullet3: Bullet = new Bullet(p.x, p.y); // Creates new bullet(s)
var bullet3Two: Bullet = new Bullet(p.x, p.y);
_bullets.add(bullet3); // Adds them to the bullet group
_bullets.add(bullet3Two);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupThreeCounter == 2) // If the player has BLUE powerup level 2...
{
var bullet3Three: Bullet = new Bullet(p.x, p.y); // Creates new bullet(s)
var bullet3Four: Bullet = new Bullet(p.x, p.y);
var bullet3Five: Bullet = new Bullet(p.x, p.y);
_bullets.add(bullet3Three); // Adds them to the bullet group
_bullets.add(bullet3Four);
_bullets.add(bullet3Five);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}

if (_powerupThreeCounter == 3) // If the player has BLUE powerup level 3...
{
var bullet3Six: Bullet = new Bullet(p.x, p.y); // Creates new bullet(s)
var bullet3Seven: Bullet = new Bullet(p.x, p.y);
var bullet3Eight: Bullet = new Bullet(p.x, p.y);
var bullet3Nine: Bullet = new Bullet(p.x, p.y);
_bullets.add(bullet3Six); // Adds them to the bullet group
_bullets.add(bullet3Seven);
_bullets.add(bullet3Eight);
_bullets.add(bullet3Nine);
FlxG.play(SoundBullet); // Plays the bullet sound effect
}
}

If everything is where it should be, then your shiny new weapons should be fully functional. Try them out!

Adding a “Start Menu”

To create a simple start menu, you’ll need to create another class in the src folder. Let’s call it MenuState.as and add the following code.


package
{
import de.pixelate.flixelprimer.PlayState;
import org.flixel.*

public class MenuState extends FlxState
{

override public function MenuState():void
{
var txt:FlxText
txt = new FlxText(0, (FlxG.width / 2) - 150, FlxG.width, "Flixel 2 Tutorial Extended")
txt.setFormat(null,48,0xFFFFFFFF,"center")
this.add(txt);

txt = new FlxText(0, FlxG.height - 35, FlxG.width, "PRESS SPACE TO START")
txt.setFormat(null, 16, 0xFFFFFFFF, "center");
this.add(txt);
}

override public function update():void
{
if (FlxG.keys.pressed("SPACE"))
{
FlxG.flash.start(0xffffffff, 0.75);
FlxG.fade.start(0xff000000, 1, onFade);
}
super.update();
}

private function onFade():void
{
FlxG.state = new PlayState();
}
}

}

Now open up your Main.as class. We need to make a change so the game know to load the MenuState first. In the constructor function where it says super(640,480,PlayState,1); change PlayState to MenuState.


package
{
import org.flixel.*;
import de.pixelate.flixelprimer.*;

[SWF(width = "640", height = "480", backgroundColor = "#000000")]
[Frame(factoryClass = "Preloader")]

public class Main extends FlxGame
{

public function Main():void
{
super(640, 480, MenuState, 1);
}

}

}

Thank you for using my tutorial. I hope it was helpful in getting you started on the Flixel/AS3 path. If all went well, your game should now look and act like the one below.

F2TE1

GO TO PART TWO

private function overlapShipPowerup(ship:Ship, powerup:Powerup):void
{
if (powerup.randomPowerupTag == “PowerupOne”) // If picking up a RED powerup…
{
_powerupOneCounter += 1; // Increases the strength of the RED powerup if the player already has it
_powerupTwoCounter = 0; // Resets the power of the other weapons
_powerupThreeCounter = 0;if (_powerupOneCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupOneCounter = 3;
}
}if (powerup.randomPowerupTag == “PowerupTwo”) // If picking up a GREEN powerup…
{
_powerupOneCounter = 0; // Resets the power of the other weapons
_powerupTwoCounter += 1; // Increases the strength of the GREEN powerup if the player already has it
_powerupThreeCounter = 0;if (_powerupTwoCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupTwoCounter = 3;
}
}if (powerup.randomPowerupTag == “PowerupThree”) // If picking up a BLUE powerup…
{
_powerupOneCounter = 0; // Resets the power of the other weapons
_powerupTwoCounter = 0;
_powerupThreeCounter += 1; // Increases the strength of the BLUE powerup if the player already has itif (_powerupThreeCounter >= 3) // Caps the power level of the weapon at 3
{
_powerupThreeCounter = 3;
}
}powerup.kill(); // Removes the powerup when it’s collected
}