Previously:
- Making a game with Flash Develop + Flixel: Part 1, Installing and Configuring
- Making a game with Flash Develop + Flixel: Part 2, Coding a simple example
- Making a game with Flash Develop + Flixel: Part 3, Input and Objects
- Making a game with Flash Develop + Flixel: Part 4, Tilemaps and Collisions
- Making a game with Flash Develop + Flixel: Part 5, Objects and Animation
- Making a game with Flash Develop + Flixel: Part 6, Cameras and Text
- Making a game with Flash Develop + Flixel: Part 7, Adding NPCs
(Want to bypass the long explanations and see the final product? Here, download this post’s code as a ZIP file.)
So far in this guide, I have written about extending many of the Flixel classes like FlxSprite, FlxTilemap and even FlxGroup. However, returning to the core trinity of Flixel objects (Preloader, Game and State), we can add more States to a game. While it needs at least one to function, Flixel has the ability to switch between them easily.
We can also start to think about States as being fundamental changes to mechanics within a game. Navigating a menu isn’t the same as moving a sprite around the screen. A character or statistics page is different too. All of these could be different states for a game to manage.
In fact, to add a simple menu to our game, we would create a new class, extend FlxState, override its update, and then wait for some input before finally switching over to the PlayState.
To have something to show to the player, we can create a simple image that has the title and some instructions like “Press Enter” or “Click to start.”

After saving that image as a part of our project, we can embed it in the MenuState as the background for the state.
We also now need to change line 17 in the ExampleRPG object.
Instead of starting with PlayState, it should launch MenuState instead.
package | |
{ | |
/** | |
* ... | |
* @author Dan Cox | |
*/ | |
import org.flixel.*; | |
[SWF(width="640",height="480",backgroundColor="#000000")] | |
[Frame(factoryClass="Preloader")] | |
public class ExampleRPG extends FlxGame | |
{ | |
public function ExampleRPG() | |
{ | |
super(320, 240, MenuState, 2); | |
forceDebugger = false; | |
} | |
} | |
} |
Note on line 29 of MenuState I’m using FlxG.fade. It’s one of several visual effect functions built into Flixel. By calling it, I tell Flixel to fade the entire viewing area for one second by filling the screen slowly with the selected color and then call a function when done. In this case, I used the color black (0xff000000) to fill the screen as a transition before moving to the PlayState.
By using effects like this, we can prevent a jarring visual switch of moving from one state to another. It also works well for moving between areas too.
In fact, we can use this as the visual transition for moving between map areas too. However, before that can happen, MapTilemap will need to change. And we will need more tiles too.

Along with our new tiles, we also need more tilemap data too.
For “house1.txt” we have:
5,9,9,9,9,9,9,9,9,4, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 3,1,1,1,1,1,1,1,1,2, 6,8,8,8,8,8,10,8,8,7
Now, we need to change MapTilemap into MapGroup.
Instead of being a single Tilemap, it will manage the different maps, switching from one to another when needed. All of the tilemap data (currently) will be embedded with MapGroup with different tilemap per set of data.
package | |
{ | |
/** | |
* ... | |
* @author Dan Cox | |
*/ | |
import org.flixel.*; | |
import org.flixel.system.FlxTile; | |
public class MapGroup extends FlxGroup | |
{ | |
[Embed(source="data/tilemap.png")] | |
private var tilemapPng:Class; | |
[Embed(source="data/houseTiles.png")] | |
private var houseTilesPng:Class; | |
[Embed(source="data/map1.txt",mimeType="application/octet-stream")] | |
private var villageTxt:Class; | |
[Embed(source="data/house1.txt",mimeType="application/octet-stream")] | |
private var house1Txt:Class; | |
private var map:FlxTilemap; | |
private var house:FlxTilemap; | |
private var previousPlace:FlxPoint; | |
public function MapGroup() | |
{ | |
map = new FlxTilemap(); | |
map.loadMap(new villageTxt, tilemapPng, 16, 16, 0, 0, 1, 2); | |
map.setTileProperties(12, FlxObject.ANY, swapHouse); | |
add(map); | |
house = new FlxTilemap(); | |
house.loadMap(new house1Txt, houseTilesPng, 16, 16, 0, 0, 1, 2); | |
house.setTileProperties(10, FlxObject.ANY, swapMap); | |
add(map); | |
previousPlace = new FlxPoint(); | |
} | |
override public function update():void | |
{ | |
super.update(); | |
FlxG.collide(Registry.player, this); | |
} | |
private function swapHouse(tile:FlxTile, player:PlayerSprite):void | |
{ | |
previousPlace.x = Registry.player.x; | |
previousPlace.y = Registry.player.y; | |
Registry.player.x = 74; | |
Registry.player.y = 64; | |
remove(map); | |
add(house); | |
} | |
private function swapMap(tile:FlxTile, player:PlayerSprite):void | |
{ | |
Registry.player.x = previousPlace.x; | |
Registry.player.y = previousPlace.y; | |
remove(house); | |
add(map); | |
} | |
} | |
} |
Using the setTileProperties function of Tilemap objects allows us to set up specific triggers and allow certain types of collisions. That way, all other tiles will collide with the player sprite but for the one value we pick (12 for the map and 10 for the house), a callback function will be called.
These callback functions have a specific ordering to their arguments too. The tile with the value is the first and the FlxObject (PlayerSprite is a FlxSprite which is a FlxObject) is the second.
In these two cases, we are ignoring them and using the MapGroup to add and remove each tilemap, moving the player as necessary.
As a final fix, we need to update PlayState to use MapGroup instead of MapTilemap:
package | |
{ | |
/** | |
* ... | |
* @author Dan Cox | |
*/ | |
import org.flixel.*; | |
public class PlayState extends FlxState | |
{ | |
private var map:MapGroup; | |
private var NPCGroup:NPCSpriteGroup; | |
public function PlayState() | |
{ | |
} | |
override public function create():void | |
{ | |
map = new MapGroup(); | |
add(map); | |
Registry.player = new PlayerSprite(32, 32); | |
add(Registry.player); | |
NPCGroup = new NPCSpriteGroup(); | |
add(NPCGroup); | |
FlxG.worldBounds = new FlxRect(0, 0, 640, 640); | |
FlxG.camera.setBounds(0, 0, 640, 640, true); | |
FlxG.camera.follow(Registry.player); | |
Registry.player.cameras = new Array(FlxG.camera); | |
} | |
override public function update():void | |
{ | |
super.update(); | |
} | |
} | |
} |
And thus, we move from the map to a room.
In Part 9, we organize the code into more modules by placing NPCs with objects representing maps, associating characters with places.