Making levels for Gravity Beam is super easy.
"Tiled is a general purpose tile map editor. It's built to be easy to use, yet flexible enough to work with varying game engines, whether your game is an RPG, platformer or Breakout clone. Tiled is free software and written in C++, using the Qt application framework."
I use Tiled to edit Gravity Beam levels. You can download it at mapeditor.org.
It was the first editor I found on a Google search for tile map editor. I wasn't expecting much, but it turned out to have exactly the right features to make making Gravity Beam levels a piece of cake: extremely easy importing of images, placement of objects and arbitrary polyline placement. It also has a very easy to understand interface, it works on any OS, and it's free!
I've included the Tiled project files (.tmx) for the built in Gravity Beam levels.
A level is a 100 tile by 100 tile map where the tiles are 16 pixels by 16 pixels. You can't have different sized levels without completely reassembling the game and ruining everything.
The map has three layers: CanvasTiles, CollisionData and GameObjects.
CanvasTiles is a tile layer, holding the indices of the tiles that make up what you see of the level.
There is a single tileset using simpletiles_color01asgradient_16_64w.png as the source image. (You can resize the tile selector by holding CTRL and using the mousewheel.)
CollisionData is an object layer that contains only polylines defining the inpenetrable interior of the level.
The polylines appear in Tiled as white lines. To create a new polyline, select Insert Polyline (the farthest right button on the toolbar), then left click once to set each point of the polyline. To stop placing lines, right click. Once you've created a polyline, you're free to move it around as a solid object or to alter its vertices individually.
The visual tiles of the level and the collision polylines are completely distinct. It's your responsibility to place polylines following the contours of the level.
Tiled doesn't care that you're making Gravity Beam levels, so you're free to create polylines of any shape anywhere in the level. If you don't specify a polyline over a region, the ship will fly over the top of it (like the messages in the sky in Levels 1 and 3). If you want your level to work, you have to follow the rules:
Here's how you make a rectangular collision area using polylines. The image on the right shows the solid area that I've created. (You don't see this in Tiled, but I have made a tool that can visualise the collision areas after the map has been exported.) Notice that the final line doesn't complete the polygon in the editor, but the collision area treats the starting and ending lines as if they extend until they connect.
GameObjects defines the starting position of the player and the box and the destination position of the box.
These are defined by placing Objects onto the GameObjects layer. Select Insert Object from the toolbar and click where you want the object. You can place the Object anywhere on the level. It'll appear as a hollow square with a smaller square inside it. The smaller square is what defines the position of the Object.
To define what the Object is, right click on it and select Object Properties. Tiled isn't restricted to only one type of game, so you'll be shown a dialogue with multiple options. The only thing that my tools use is the position of the Object and the Type of the object. The Name and size of the Object and the name-value property box are not used.
There are three valid Types: PlayerStart, BoxStart and BoxDestination. Type one of these names into the Type field and you've made the object.
You can set up Tiled to highlight these Object Types in different colours if you go to Edit, Preferences, Object Types and then insert some entries defining the colours.
Once you've laid out the tiles, specified all the collision polylines, placed the player and box positions, it's time to export the level.
Go to File, Export As and export the map as a Json file. A Json file is a structured plaintext format that stores its data in a hierarchical key-value tree format. It's useful because it means we can use Javascript to parse the file and retrieve data by asking for what appears at a given path.
If we assign the Json object to the variable myjson, the three layers can be found at myjson.layers[n] where n is 0, 1 or 2. I iterate through values of n to find the layer with the right name. I could assume the positions of the layers in the Json file based on their positions in the Tiled layer stack, but they might not always end up in the same places.
json_to_ascii.htm is a HTML file containing a Javascript script that reads the Json tree from var myjson and produces copy-pasteable HTML output that can be further processed to make the level.
It does two things: it gets the tileset data and makes it zero-based to match how the game executable expects it, and it gets the polyline data and converts it absolute positioning relative to the top left corner of the map.
To use json_to_ascii.htm, copy the complete contents of your exported Json file at the top as var mysjon = {.... Then save it and open the file in a web browser. The output should appear as a plaintext list similar to the following:
newpolygon 222,1172 222,612 40,613 endpolygon newpolygon 112,656 112,576 48,576 48,656 endpolygon newpolygon 96,656 96,560 64,560 64,624 endpolygon
This list is a plaintext representation of all the polylines in the level. A newpolygon, endpolygon pair defines a polyline and each pair of coordinates places a vertex. These are pixel coordinates starting from the top left. (This file format is how the very first Gravity Beam test levels were produced, back when the data was entered manually. I'm incredibly thankful for Tiled.)
Near the bottom of the HTML output, you will find the following:
End of polyline definitions. ------------ dc.l 1408<<8; Player x dc.l 1328<<8; Player y dc.l 744<<8; Box x dc.l 401<<8; Boy y dc.l 1408<<8; Box destination x dc.l 1334<<8; Boy destination y ; Level tile map data follows. dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
This text, from the horizontal rule onwards, is a series of vasm compatible data declarations defining the object positions and tilemap indices for your level. This should be copied from the browser window into the file level1_levelmap.asm. This file is then used in the level_manufact to produce a single binary file holding the active in-game level information.
The polylines require further processing separately.
To process the polylines, you need to copy all of the output from the first newpolygon line to the final endpolygon line to a new text file and save it.
Then run polygonpreparer_v2.exe input_level1_polygonascii.txt output_level1_polygonbinary.bin.
polygonpreparer_v2.exe reads the newpolygon-endpolygon plaintext file and performs the processing described in the other document.
The output is the polygon definitions as an Amiga-friendly binary file that should be incbinned into the game source. Together, the plaintext tilemap file and this polygon binary file define the entire level and appear as one continuous block of data under the label Level0LevelDataHeader:.
The console output of polygonpreparer_v2.exe shows the progress of the preparation: the first pass shows the vector values of A, B and B' and the calculated values of the three constants, the second pass shows the split-space activation determination.
Once the conversion of the collision data is complete, it's not easy to test it. You can't inspect the file manually; that'd take ages.
polygoncollisionimager_v2.exe is a tool that takes a polygon binary file as input and produces a 1600 by 1600 TGA image file showing the interior collision area as output.
Usage: polygoncollisionimager_v2.exe level1_polygonbinary.bin output_collision.tga
The output will have shades of red and yellow in the interior and black in free space. You use the Tiled editor to export a PNG image of your level's layout to compare the two.
(There was a 'not v2' version of these files; that was before I used the split-space bitmask.)