Creating a Flash platform game with Flixel and Flex – Adding a player

PLAY THE DEMO

DOWNLOAD THE SOURCE CODE

TUTORIAL INDEX

The first thing we need to do is leave the menu state for a new state called GameState. To do this we override the update function in the MenuState class, and watch to see if the X key has just been pressed. The background image has been changed from “Press any key” to “Press the X key”.

public override function update():void
{
super.update();
if (FlxG.keys.justPressed(“X”))
FlxG.switchState(GameState);
}

Most Flixel classes have an update function. It provides a way to update an object, like moving a player along the screen, watching for key pressed, or firing a bullet. In fact most of your game logic will exist in update functions.

For the MenuState class, the update function uses the justPressed function of the static keys object held by the FlxG class. If it has been pressed we switch to the new GameState state by calling the FlxG switchState function.

You can think of FlxG as a kind of utility class that contains a number of common static properties and functions. The FlxG class will be referenced quite a bit from our game.

The GameState class will be responsible for creating the level and initialising the player.

package
{
import org.flixel.*;

public class GameState extends FlxState
{
[Embed(source=”../media/tech_tiles.png”)]
protected var TechTilesImage:Class;

protected var levelBlocks:FlxArray = new FlxArray();
protected var player:Player = null;

We embed an image that will be used to display the individual blocks that will make up the level, and define to variables: one for the player, and a FlxArray collection that will hold the level blocks.

public function GameState()
{
levelBlocks.add(this.add(new FlxBlock(0,640-24,640,8,TechTilesImage)));

player = new Player();
this.add(player);
FlxG.follow(player,2.5);
FlxG.followAdjust(0.5,0.0);
FlxG.followBounds(0,0,640,640);
}

In the constructor we create a new instance of the FlxBlock class. Here we are defining a single block that stretches along the bottom of the screen. The FlxBlock will randomly fill the area using the tiles inside the supplied image. Each tile in the image is assumed to be as wide as the whole image is high. So if you were to supply an image 8 pixels high, it would have to be a multiple of 8 pixels wide (like 16, 32, 64 etc), and each tile is assumed to be 8 pixels wide. The image below is from the demo game Mode. It is 8 pixels high, and 120 pixels wide, which means it contains 15 individual tiles.

Next we create a new instance of the Player class.

We then instruct the Flixel engine to follow the player as it moves around the screen using the FlxG follow function.

The followAdjust function tells Flixel not to keep the player directly in the centre of the screen, but to lead the camera by a percentage of the targets velocity. This gives the camera some “bounce”.

Finally we use the followBounds function to define how far the camera will scroll. This is used to essentially define the edge of the level. Note that this does not stop the player from running off the edge, which when you play the demo you will see he does quite happily. It just stops the camera from scrolling past the edge of the level.

public override function update():void
{
super.update();
FlxG.collideArray(levelBlocks, player);
}

}
}

The FlxG collideArray function will detect any collisions between the player and the level blocks. By calling this function every frame we can prevent the player from running and falling through the level blocks.

The final addition for this demo is the Player class.

package
{
import org.flixel.*;

public class Player extends FlxSprite
{
[Embed(source=”../media/spaceman.png”)]
protected var PlayerImage:Class;

protected static const PLAYER_START_X:int = 300;
protected static const PLAYER_START_Y:int = 300;
protected static const PLAYER_RUN_SPEED:int = 80;
protected static const GRAVITY_ACCELERATION:Number = 420;
protected static const JUMP_ACCELERATION:Number = 200;

We being by embedding the image that will be used to display the player, and specifying some constants that define how the player will move.

public function Player()
{
super(PlayerImage, PLAYER_START_X, PLAYER_START_Y, true, true);

drag.x = PLAYER_RUN_SPEED * 8;
acceleration.y = GRAVITY_ACCELERATION;
maxVelocity.x = PLAYER_RUN_SPEED;
maxVelocity.y = JUMP_ACCELERATION;

addAnimation(“idle”, [0]);
addAnimation(“run”, [1, 2, 3, 0], 12);
addAnimation(“jump”, [4]);
addAnimation(“idle_up”, [5]);
addAnimation(“run_up”, [6, 7, 8, 5], 12);
addAnimation(“jump_up”, [9]);
addAnimation(“jump_down”, [10]);
}

First the underlying FlxSprite class is initialised. We specify the x and y position, the image that the player will be displaying, and we set both the Animated and Reverse parameters to true to indicate that the player will be animated, and that we want the animated to be horizontally reversed depending on which way the player is facing.

The movement of the player is defined by a number of factors. We start by specifying the players drag along the x axis. This can be thought of as friction. Having some drag means that player will not accelerate from 0 to full speed as soon as a movement key is pressed, and it also means he won’t “stop on a dime” when the movement key is released.

Next we assign a value to the acceleration in the y axis. This is effectively defining gravity.

In order to stop the player from forever picking up speed as he runs or falls we set limits on the maximum velocity he can reach in the x and y axes with the maxVelocity variable.

Next we define the animation frames for the player. Just like the blocks above, the players source image contains a number of individual frames, with each frame assumed to be as wide as the entire image is high. Our source image contains 11 frames of animation, which we assign to a number of named animations (the animation names are up to you).

public override function update():void
{
acceleration.x = 0;
if(FlxG.keys.LEFT)
{
facing = LEFT;
acceleration.x = -drag.x;
}
else if(FlxG.keys.RIGHT)
{
facing = RIGHT;
acceleration.x = drag.x;
}
if(FlxG.keys.justPressed(“X”) && !velocity.y)
{
velocity.y = -JUMP_ACCELERATION;
}

if(velocity.y != 0)
{
play(“jump”);
}
else if(velocity.x == 0)
{
play(“idle”);
}
else
{
play(“run”);
}

super.update();
}

}
}

In the update function we modify the players velocity, acceleration and current animation depending on what keys have been pressed and how the player is moving. The code is reasonably straight forward, except for maybe the facing property, which is used to indicate which way the player is facing. This is used by the FlxSprite class to reverse the image on the screen if the player is facing the opposite direction to the way the source image was originally drawn.

We then call the FlxSprite update function, which takes care of updating the position of the player based on its velocity and acceleration. The underlying functions used to calculate the physics do not use the “proper” integration formulas for acceleration over time, but since the frame rate is fixed (at 90 frames per second while the game is not paused) the results of the calculations are consistent, and good enough for a simple Flash game.

When you play the game your player will drop to the ground and collide with the block we have placed down the bottom of the screen. You can then run around with the arrow keys and jump with the X key.

By now you should be getting a sense of how easy it is to make a game with Flixel. For the most part you simply supply the logic for the game, and let Flixel work out how everything fits together behind the scenes. In the next tutorial we will add some weapons for the player to fire.

Leave a Reply

Your email address will not be published. Required fields are marked *