Map editor tutorial
From Post-Apocalyptic RPG wiki
This tutorial explains how to build your own map for PARPG from scratch.
Starting the map editor
To start the map editor CD into your PARPG directory and run parpg_editor.py. This Python script is basically a wrapper around FIFE's official map editor that comes with a workaround to load and save some custom map attributes that are used by PARPG but aren't natively supported by FIFE.
At the moment we rely on a hardcoded folder structure so the trunk/game and the trunk/tools directories need to reside in the same root folder:
You won't be able to start the editor if you're utilizing a different folder structure.
Creating a new map
We want to create a new map from scratch so let's select [File] >> [New map]
Choosing a map identifier
Every PARPG map needs a unique map name as identifier. Let's call it "testmap" for now:
Creating a first layer
FIFE uses a layer concept for its maps. Layers determine the drawing order of objects (lower layer is drawn before higher layer). As a rule of thumb, objects that interact with each other should be placed in the same layer.
For example, players and buildings are at the same general height (for example, a player can move behind a building, or go inside it) and so should exist on the same layer. "Tiles" for ground and water generally are under the player, so they can go in a lower layer. Higher stuff like airplanes and clouds should exist in a third layer.
Three layers (ground, object, air) should usually be enough, although more creative usage of layers will surely occur. We'll start with ground layer. Just enter the layer id, you can ignore the other layer attributes for now:
- Pathfinding strategy is only relevant to layers where pathfinding should happen. This ususally happens on the object layer so we don't need to care about it for the ground layer.
- Grid type determines if either a square or a hex grid is used. PARPG uses square tiles for the ground, so we don't change that setting for the ground layer.
- Rotation gives you the chance to rotate the layer itself. This is not needed for PARPG.
- Scale determines the x and y scale for the ground layer should and should be 1.0 in this case. Additional layers can have the same size (x and y = 1.0), be larger (x and/or y > 1.0) or smaller (x and/or y < 1.0) than the ground layer.
- Offset determines specific shifts to the layer placement. This is useful once you use additional layers to allign them to each other if different scales are used.
- Transparency determines how transparent or opaque a layer is. We stick to the standard setting of 0 as the ground layer should not be transparent at all.
Creating the map camera
PARPG uses so called perfect isometric. That means that the height of a tile is half the width of it. These are the settings we use:
- Rotation: 45°
- Tilt: 60°
- Height: 36px
- Width: 72px
You can use the FIFE geometry twister tool to understand how the system actually works. The tool can be found in <FIFE>/utils/geometry_twister.py.
That's the PARPG geometry visualized via geometry_twister.py:
Note: right now PARPG uses a bunch 70*36px tiles for legacy reasons. We have switched to 72*36px tiles and will try to replace the slightly smaller legacy tiles in the long run.
Filling in the camera data
So let's set up the camera in the editor:
Note that in this screenshot the camera is configured with a viewport of 0,0,640,480 (meaning the camera will render a surface between points (0,0) and (640,480)), within PARPG this setting is ignored and the viewport is set to the resolution of the PARPG window, this way we automatically make use of the available screensize.
Importing the PARPG assets
Now we need to get our custom PARPG assets into the map editor. To do so, choose [File] >> [Import directory] from the menu:
Selecting the right directory to import
As all relevant PARPG assets reside in <PARPG>/objects, browse into this folder and click on the [Select] button. Now all PARPG assets will be imported:
The object selector
To check out if importing the assets has actually worked out, we open the object selector tool via [Tools] >> [Object selector].
Object selector interface
Now the object selector shows the PARPG assets. You can move the object selector window around and attach it to certain areas of the screen, e.g. the borders. Choose a place for it and attach it there, e.g. the right side of the screen as shown here:
The tools interface
Now that we have our assets imported, we can start to actually place them on the map. We'll start by adding tiles to the ground layer. The map editor is pretty much like an 2d image editing tool, the toolbox offers you the following choices:
- Select specific cells
- Move already placed instances around on the map
- Place new instances of objects on the map
- Remove already placed instances from the map
- Select and copy already placed instances; this is some kind of stamp functionality that copies the selected instance so you can paste it elsewhere on the map via the placing tool
Instances vs objects
In case you're confused and can't figure out what instances and what objects are. Instances are just objects that are placed on the map. So you can have multiple instances of the very same object, e.g. a ground tile on the same map.
Placing ground tiles
Let's keep it simple for now, so we just add a lot of snow tiles to the ground layer. That will do it for now. Use the instance placing tool for this purpose:
Adding a second layer to the map
Now that we got some ground tiles in place, we should add some additional objects to the map. So now we'll add a second layer, called "objects", where the map objects reside and collision and pathfinding happens.
Adding the objects layer
To add such a second layer to the map, click on the [+] icon of the layer tool. Just use "objects" as layer id and "cell_edges_and_diagonals" as pathfinding strategy. The pathfinding strategy decides if map instances like characters can just move into four directions (diagonals), eight directions (cell edges & diagonals) or even move in a freeform way. We're going for eight directions. You could use the editor presets for all other fields. We don't need to customize rotation and scale as we want to use the same grid geometry that the ground layer features for the objects layer as well:
Finding the center point of large objects
Whenever you add larger objects to a map, you will need to worry about proper z-ordering. In short, z-ordering decides which objects to draw in front and which objects to draw behind others. To avoid z-ordering issues, you'll need to figure out the correct center point of an object and apply x & y shifts to implement this center point.
Here's an illustration of the problem:
The red dot is the center point chosen by the engine that we're utilizing: FIFE. FIFE will automatically assume that the center point of an object is x = object width/2, y = object height/2. This is a very rough guess and only works for very small objects. To find the correct center point, we need to identify the base plane of the object first. We've marked the (simplied) base plane of the building with green lines in the example. If we'll connect the edges of the plane that have not been connected with each other yet (blue lines), we have already found the correct center point of the object. The correct center point is where the blue lines intersect; it's the center point of the base plane of the object.
We can now calculate the x & y shifts that need to be applied to the object to have a correct center point. Measure the distance between real center point and the one calculated by the engine. For our example it's roughly x= 50px, y= -80px. We can now open the object file, in our case container_house01.xml and adjust the x & y offsets from x_offset="0" y_offset="0" to x_offset="50" y_offset="-80". Save the modified object xml file and we're done.
Don't worry about pixel perfection when it comes to the offsets. You can avoid z-ordering problems as long as the chosen center point lies within the base plane of the object.
Adding large objects and blockers
Now that we've implemented the correct center point for our objects, we can add them to the map without worrying about z-ordering issues anymore. However we do still need to worry about collision detection. To avoid that a moving instance such as the player character collides with other large map instances, we'll need to add blockers. These blockers are only needed if the map instance that the player could collide with is larger than the size of a base tile.
Now that the object in question, the container house, is far larger than our 72*36px base tiles, we'll have to add invisible blockers to the map. They can be found in the object selector under "block". For the purpose of easier illustration the following screenshot shows how to place the blockers without any ground tiles added:
Now we should add some ground snow tiles to it: