Twofold Secret

Regions and RegionHistory

One of the conundrums you might face while using Flixel is the idea of multiple areas. Here’s an example from Super Mario Bros. 3. Skip to 3:15 to see the player take a quick diversion off the main map to collect some coins and then return to finish off the level he left.

Our own game Where We Remain consists of an island overworld and a series of caves. These caves are independent places that the player should be able to go in and out of whenever he wishes. The game also needs to remember the state of each place, so that he can’t collect the same powerup over and over again just by re-entering the cave.

Flixel uses the FlxState class to represent a state of play — e.g. a title screen, high score display, or the main gameplay. I was at first inclined to use FlxStates to represent different areas of play, too, but the problem is, each time you call FlxG.switchState(), a new instance of the state class is created. This makes it hard to remember state. The only way to do it would be to use static variables, but this would quickly get confusing — it might be doable with just one cave, but on expert mode we have 12.

There are a lot of ways to approach the problem, but here’s how I tackled it. I defined a class called Region that is essentially a collection of FlxLayers along with a FlxSprite for the player. These FlxLayers are mainly for convenience’s sake — these were what my overworld and caves shared in common, but you should customize the Region class for your own needs. My Cave and Overworld classes were descendants of Region that did all the setup work in their constructors — e.g. map creation, enemy placement, and so on.

I then have a class called RegionHistory that manages the player’s movement through these regions. It’s basically an array of states that records the player’s position. As the player moves through different regions, a region calls RegionHistory.switchRegion(). This method remembers the player’s position in the current region, so that, for example, when you walk out of a cave in WWR, it knows which cave mouth to put you back on in the overworld. It also puts the current region to sleep, as it were, by setting all of its layers’ active and visible properties to false. It then activates the next region by setting all of its layers’ active and visible properties to true.

Important note: because of the way Flixel’s update cycle works, all other sprites have a shot at updating themselves even after another sprite has called switchRegion(). This is usually harmless, but if you need to prevent it, make sure to have the sprite check RegionHistory.currentRegion().active in its update() method.

As icing on the cake, RegionHistory allows Regions to listen in on three events: onEnter, when the player enters a region for the first time; onReturn, when he comes back; and onExit, right before he leaves. This allows for some basic cleanup work — for example, setting the camera bounds correctly. Regions otherwise don’t have to worry about switching between them. RegionHistory takes care of positioning the player sprite where the region expects it to be, and sprites in an inactive region never receive update() calls.

Download source code (unzip, place in your project’s src/ folder to use)

nb. This code was designed for Flixel 1.25, so if you plan to use it in a more recent release, you’ll have to do a little fixup work to make it work with the constructor changes that were introduced in version 1.40.