Creation of a platform game using FlashPunk

Read all posts about "" game

During these days I am playing a bit with FlashPunk and I want to share with you a couple of examples.

We are going to build a simple platform game.

Getting the required software

While most developers use Flash Builder or FlashDevelop, I will use Flash Professional CS5.5, so the first thing you should do is getting a copy of it. You can get a fully functional 30 days trial at this page.

Then, download the latest release of FlashPunk from this page, and you are ready to go.

Preparing the worspace

All in all, FlashPunk is just an AS3 library, and although it has been developed for being used outside the Flash IDE, you just have to copy the net foder into your project folder and you are ready to go.

Hello FlashPunk

At this time in your main class (I called mine punk), enter this code:

package {
	import net.flashpunk.Engine;
	import net.flashpunk.FP;
	public class punk extends Engine {
		public function punk() {
			super(640,480,60,false);
		}
	}
}

I said FlashPunk has been developed for being used outside the Flash IDE, and that’s it… we haven’t Sprites or Movieclips, but the class extends Engine FlashPunk’s class.

This line

super(640,480,60,false);

Calls the constructor of the extended class, that is Engine constructor, with these arguments:

width: the width of your game in pixels

height: the height of your game in pixels

frameRate: the game framerate, in frames per second (default: 60)

fixed: true if a fixed-framerate should be used, false (default) otherwise.

Test the movie and you will see a dark background color, no matter the Stage color.

Your FlashPunk project works!

Adding some walls

When it’s time to add graphics to our FlashPunk games, we have to draw them with our preferred paint software. Using Photoshop, I made a 32×32 pixels square and called saved it as wall.png in a newly created assets folder in the same level of net (the one which contains FlashPunk library).

Then change punk.as this way:

package {
	import net.flashpunk.Engine;
	import net.flashpunk.FP;
	public class punk extends Engine {
		public function punk() {
			super(640,480,60,false);
		}
		override public function init():void {
			FP.screen.color = 0x222233;
			FP.world=new theWorld();
		}
	}
}

What happened? We added a new function called init, overriding the init method of Engine(). This will allow us to initialize the game. FP.screen.color lets us set the background color, specified as an hexadecimal value.

Then, we define world, the main game container, with theWorld class. This class will contain the game itself.

Let’s see the content of theWorld.as:

package {
	import net.flashpunk.World;
	public class theWorld extends World {
		public function theWorld() {
			for (var i:int=0; i<20; i++) {
				add(new theWall(i,0));
				add(new theWall(i,14));
			}
			for (i=0; i<14; i++) {
				add(new theWall(0,i));
				add(new theWall(19,i));
			}
			for (i=1; i<5; i++) {
				add(new theWall(5-i,14-i));
				add(new theWall(8+i,5+i));
				add(new theWall(2+i,10-i));
				add(new theWall(13+i,8-i));
			}
		}
	}
}

There isn't that much to say, we are just creating a lot of theWall instances. So the interesting part comes with the creation of theWall.as:

package {
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;
	public class theWall extends Entity {
		[Embed(source='assets/wall.png')]
		private const WALL:Class;
		public function theWall(posX:int,posY:int) {
			graphic=new Image(WALL);
			setHitbox(32,32);
			type="wall"; 
			x=posX*32;
			y=posY*32;
		}
	}
}

As you can see, the class extends FlashPunk's Entity class.

At lines 5 and 6 the wall picture is embedded into a class called WALL.

Then the constructor wants the column and row position as arguments.

Line 8: Assigns the wall picture to theWall entity. This way, at every theWall instance, our wall.png pucture will be added to stage.

Line 9: setHitbox method defines the hit box around the entity, useful when we'll have to deal with collisions. It works in the same way as the hit box used for collision tests with AS3.

Line 10: type property is useful to group entities. This way we'll only have to check for collision with wall group rather than for each theWall entity.

Lines 11-12: simply placing the entity in the world.

This is our game at this step:

Only a bunch of walls. Let's add the player.

Adding the player

Using Photoshop, I created a cyan 13x26 pixels box and saved as player.png in assets folder.

Just like I added the walls, I am adding the player in theWorld class at line 5

package {
	import net.flashpunk.World;
	public class theWorld extends World {
		public function theWorld() {
			add(new thePlayer);
			for (var i:int=0; i<20; i++) {
				add(new theWall(i,0));
				add(new theWall(i,14));
			}
			for (i=0; i<14; i++) {
				add(new theWall(0,i));
				add(new theWall(19,i));
			}
			for (i=1; i<5; i++) {
				add(new theWall(5-i,14-i));
				add(new theWall(8+i,5+i));
				add(new theWall(2+i,10-i));
				add(new theWall(13+i,8-i));
			}
		}
	}
}

thePlayer class will extend Entity and it's the latest class we will add in this tutorial. It's a bit longer than the previous classes, but not that hard to understand:

package {
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.utils.Input;
	import net.flashpunk.utils.Key;
	import net.flashpunk.FP;
	public class thePlayer extends Entity {
		private var power:Number=0.2;
		private var jumpPower:Number=10;
		private var hFriction:Number=0.95;
		private var vFriction:Number=0.99;
		private var xSpeed:Number=0;
		private var ySpeed:Number=0;
		private var onTheGround:Boolean=false;
		private var gravity:Number=0.3;
		[Embed(source='assets/player.png')]
		private const PLAYER:Class;
		public function thePlayer() {
			graphic=new Image(PLAYER);
			setHitbox(13,26);
			x=305;
			y=225;
		}
		override public function update():void {
			var pressed:Boolean=false;
			if (Input.check(Key.LEFT)) {
				xSpeed-=power;
				pressed=true;
			}
			if (Input.check(Key.RIGHT)) {
				xSpeed+=power;
				pressed=true;
			}
			if (collide("wall",x,y+1)) {
				onTheGround=true;
				ySpeed=0;
				if (Input.check(Key.UP)) {
					ySpeed-=jumpPower;
				}
			} else {
				ySpeed+=gravity;
			}
			if (Math.abs(xSpeed)<1&&! pressed) {
				xSpeed=0;
			}
			xSpeed*=hFriction;
			ySpeed*=vFriction;
			adjustXPosition();
			adjustYPosition();
		}
		private function adjustXPosition():void {
			for (var i:int=0; i

First, let's have a look at the class level variables:

private var power:Number=0.2;
private var jumpPower:Number=10;
private var hFriction:Number=0.95;
private var vFriction:Number=0.99;
private var xSpeed:Number=0;
private var ySpeed:Number=0;
private var gravity:Number=0.3;

power is the thrust for the horizontal speed
jumpPower is the thrust for the jump
hFriction is the horizontal friction
vFriction is the vertical friction
xSpeed is the horizontal speed
ySpeed is the vertical speed
false otherwise
gravity is the gravity force

Then, in the same way as the wall, player.png image is embedded in a class called PLAYER.

At lines 18-21 I define player's image, hit box and position in the same way I made with the walls.

The update function I had to override manages player movement:

Line 24: a local variable called pressed is created and takes a false value. This variable will be true if the player is pressing left or right arrow keys, false otherwise.

Line 25: here is how FlashPunk checks for pressed keys, in this case left arrow key.

Line 26: adjusts horizontal speed

Line 27: we now know the player pressed the left (or right) arrow key

Lines 29-32: same thing when the player pressed the right arrow key

Line 33: this is how FlashPunk checks for collisions: collide method wants three arguments: the entity or group of entities to check for the collision (wall group in this case, that is any theWall entity), and the x and y position where the entity is supposed to be placed.

In this specific case I am checking if the player, placed one pixel below its actual position, is colliding with the walls. That is, the player is on a platform.

If the player is on a platform, we set its vertical speed to zero (line 34) and check if the player is pressing up arrow key (line 35). In this case, the vertical speed is updated by subtracting jumpPower. This is how the player jumps!

If the player is not on a platform (line 38), the vertical speed is updated by adding the gravity.

Lines 41-43: stop player movement if it's too slow and the player is not pressing left or right arrow keys.

Lines 44-45: apply friction to player's speed.

Lines 46-47: adjust player x and y position according to its speed and the environment. This is made with adjustXPosition and adjustYPosition functions which work in the same way, moving the player in the current direction pixel by pixel until the movement is completed or the player hits a wall.

Let's see how does adjustXPosition work:

Line 50: loop from zero to the absolute value of horizontal speed

Line 51: checks for collision with a wall one pixel on the left or on the right of the player, according to its horizontal speed. sign method returns 1 is its argument is positive, -1 if it's negative and 0 if it's zero.

Line 52: if there's no collision, increases/decreases player x position according to its horizontal speed.

Lines 54-55: if there is a collision, set the horizontal speed to zero and exit the loop.

adjustYPosition works in the same way.

This is the final result:

Use left/right arrow keys to move, up to jump.

Download the source code, with FlashPunk library, and all the graphic assets.

Is there any other feature you would like to see?

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers