There’s an earlier post that goes into more specifics with the XML, although this post covers it as well. , which was written when I was doing this groundwork back in March.
First we have the ideas that need to be implemented – after I design some dungeon rooms or program some enemies, it’s time to put them into the map editor, which is a way to make your levels and export them into data that the game can use to create the actual areas. The map editor I use is DAME, which works well with Flixel, the AS3 framework I use for Anodyne.
The game’s maps are tiled in the editor and export to plain text in the CSV format – just lines of comma-separated numbers which correspond to specific tiles.
The CSV is then read by the game, and in conjunction with a tileset .png image file, creates the in-game environment, and additionally sets properties for tiles – such as callbacks (for holes), or whether or not you can walk on the tile.
The entities (treasure boxes, enemies, etc.) are also placed inside of DAME, but instead export to XML. There’s an earlier post on the specifics, but each map in the game exports a bunch of sprites for that map, as well as some metadata that I use in-game to give certain behaviors, and also the x and y coordinates. In the game, there are “field” areas and “dungeon” areas.
In field areas, the camera moves with the player, much like platformers. These areas are more for transitory, open-world like places. Currently, I just spawn all the sprites at once, which obviously isn’t very efficient. I don’t want to waste time optimizing what works fine, so if I reach the point where performance takes a hit I’ll probably stick in a distance metric that determines whether I bother updating a sprite, that has some timeout to see if the sprite should be revived.
Anyways…on to the dungeon areas.
The dungeon areas are a little more interesting. Although the entire map CSV is loaded into memory, only two 10×10 chunks of tiles are actively being drawn at once, and only sprites from one 10×10 section are being updated, to increase performance.
When you first enter a dungeon area, the initial chunk is loaded, and that’s where the player is instantiated. Then, I set a few bounds where if the player crosses them, we freeze the controls, load the next chunk into memory, and pan the camera to the next room. This way, I only need to maintain 3 tilemap objects, one, which contains the entire map in memory stored as an array, which makes it easier to obtain chunks for the 10×10 rooms. And then two 10×10 chunks because we want the previous room to still show when scrolling – so when we transition rooms, the current map buffer sends its data to a previous map buffer, and the current map buffer loads the next map.
The sprites also have to be arranged a little differently to load them on a per-room basis, so once at the start of the game, we take the very wide XML tree, and determine what sprites fall into which rooms, and create subtrees for each room. This way when we enter a room, we just lookup that tree and instantiate all of its entities.
During a transition, I also move all the old sprites from the room being moved out to another array so that they still appear, and I then clear them out of memory once the map completely moves over. This way we don’t have an awkward disappearance of all the enemies in one room as we transition, and we additionally see all the entities in the next room as we transition.
The entire game’s XML is serialized, as the XML stores the state of enemies that are needed to be permanently dead (bosses), or entities that need to stay open forever once opened (gates, locked doors).
This means that updating a released version isn’t really an option, as we’d need a way to patch the game’s XML tree. Oh well. But it’s not like I want to release a game that isn’t content complete, so it’s not really an issue, I’d hope. Will just have to be careful with save bugs, which we will hopefully iron out in testing and so forth.
That’s the general idea for all of the dataflow, and there’s not much magic going on. Maybe later I’ll talk about how some of the basic entities work and communicate, which also isn’t particularly complex since only a limited set of entities actually interact with eachother, by design, for simplicity. Or, how I go about bosses, or the player interactions…hm.
If you’d like to know anything very specific about this process let me know and I’ll write something up about it!