Map Making

The new game needs a new map, so I thought it might be interesting to go over the technical process involved in creating a functional map.

Six Ages (like King of Dragon Pass) divides the local map into zones (such as the Imther Mountains), as well as hexagons. Exploration reveals new hexes. Which zone you’re exploring influences the results (as with most things in the game, it’s not purely deterministic).

I draw each zone as a separate layer in Photoshop, giving it the name of the zone. Then I use File > Export > Layers to Files to create separate PNG files. I actually do this twice, once to create trimmed images that can be used for hit-testing, the second to get the metrics of each zone. The command takes nearly 9 minutes to run on a recent MacBook Pro.

Photoshop exports the layers with file names like _0002s_0002s_0001_Vestantes.png, so I run a couple bash scripts to clean that up

for f in *.png; do mv $f ${f/${f:0:12}/}; done
for f in _*.png; do mv $f ${f/${f:0:6}/}; done

to leave me with Vestantes.png.

The untrimmed images are each 1500 x 1375 pixels (in the case of “Ride Like the Wind”). I feed these through TexturePacker, which is designed to find the unused pixels and combine the images into a single sprite sheet. This is important with some graphics systems, but I actually ignore the image. What I’m after is the metadata, which describes the bounding box and position of each image within the overall picture — i.e. its geometry, where it is on the map. I use Lua to specify the game’s data, so I have TexturePacker export for the Corona SDK. Corona uses Lua, so I can use the same data files even though I’m not using Corona. A typical zone looks like

{
	-- Vestantes
	x=1088,
	y=2,
	width=434,
	height=317,

	sourceX = 0,
	sourceY = 775,
	sourceWidth = 1500,
	sourceHeight = 1375
},

so I can do hit-testing based on the 434 × 317 size of the zone. I also create a separate metadata file, which describes the features of each zone:

["Vestantes"] = {flags = kFeature + kAcrossOslira, label = "Vestenan", labelVariable = "showVestantes"},

(This is an explorable feature, that requires crossing the Oslira River to visit. Once discovered, it’s labeled on the map.) There’s a bit of sanity checking in the game to make sure every zone has its feature data, which is useful during development (the data is spread between two files so that the geometry can be regenerated if something changes).

Clan zones need special attention. Is a clan that has claimed the zone NBE1 adjacent to a clan in NBE2? This is additional metadata:

["NBE1"] = {neighbors = {"NBE2", "NBE3", "SO1"}, flags = kRiver},

To help edit this, there’s a special debugging mode which shows the connections. There’s some sanity checking code for this too, though it’s mostly a manual process.

The first time through this, I noticed there were some stray pixels in one of the layers (and had to run TexturePacker again). But it’s a pretty straightforward process.

The final step (before testing in actual play) is to make sure the number of exploration hexes is correct.

The new map is ready to go, much earlier in the process than with the first game.

Author: David

Creator of Six Ages and King of Dragon Pass