Map-making tutorial

    How are maps made?

Retro Flight maps are just a big text file listing information about the map, such as where the objects in the map are and how big they are. All you need to do to change a map is to edit this text, and you can copy things from one map to another by pasting text from one map to another.

So that the game can understand this text, it's written in a standard, human-readable notation called JSON. I'll show you step-by-step what you need to do in this tutorial, so you'll be able to get by for now without knowing how JSON works. The main thing you do need to watch out for is that the brackets match up correctly.

When you've finished the tutorial and want to make your own maps for others to play, you should learn a bit about JSON first so you don't make too many mistakes.

In case you get an error while doing the tutorial and can't see what you mistyped, or you're just already curious about JSON, here are a few links to JSON resources. You might find them a bit tricky, but don't worry, you don't need to understand it all, just the basic ideas. If you can find any tutorials more suitable for non-technical readers, please let me know!

JSON tutorial by w3schools

An introduction to JSON

Introducing JSON

Wikipedia page

    Downloading sample maps

There are some sample maps on the Play Maps page on the web site, with instructions for how to download them to the app, via the maps slider on the options menu.. For example, the map SandboxWithToys.json places the player on a racetrack with some different vehicle types around them.

You can download and play around in that map for a while if you like, but don't forget to come back!

The map we're going to edit for this tutorial is the Empty Map, and it looks like this:

Not very exciting yet - it's just sea, some land and a helicopter - but it's a much easier starting point for learning maps. By the time we've finished the tutorial, there'll be 12 black helicopters there fighting a flying saucer. Once you've got the hang of it, you can mess around with bigger maps right from the start.

Download the map called EmptyMap.json to your computer and have a look at it. Don't worry if you don't understand it yet.

It's better to open the file in a JSON editor, or at least an editor that understands JSON, because they will usually color it in cleverly, making it easier to read.

It's just plain text so you can view it in your usual text editor if you don't mind not getting the nice coloring, but it might not want to load it at first because it doesn't know the '.json' file extension. If this happens, just change the filename to end in .txt instead of .json so that your text editor will open it. The game will still be able to understand it!

    How to get your new maps into the game

Now, we need to be able to change this file, and upload the changed version to your app. In the Custom Maps page in the app, you could edit the JSON text in the bottom box then click "Validate" so that the app will use the new JSON, or you could copy text from another app on your phone and paste it into that box. But that's all a bit fiddly, especially when you're making big maps. The best way to do it is to edit the JSON file on your computer, then copy or upload the file to the web, then download the file to your device.

There are lots of "paste bin" sites that will let you paste in text, then give you a URL you can download it back from. One thing you do have to watch out for is that for some of these sites, the URL doesn't point to plain text, but to a page on their site with lots of graphics and a box with some text inside it. You can't download that to the app! You need a site that will let you download the JSON in it's raw form.

If it doesn't work, please go over the steps again and get this working before you continue, or you won't be able to upload your new maps.

    The metadata

There are two top-level keys. One of them is an Array (i.e. a list) of "Cluster Instances", which tells the game about all the objects in the world, such as the choppers, the buildings and the Sea. More about this later.

The other one is a Dictionary (i.e. a bunch of key-value pairs) of "Meta Information" about the map file as a whole, such as the name of the map's author.

Now that it's your map and not mine, let's change the author. Edit your copy of the file, and next to "Author", where it says "Michael Howard", remove that and put your own name. Make sure that you only change the text between the quotation marks.

Each metadata object, including the map boundaries, is explained in this map making reference guide. You don't really need to worry about that reference guide yet unless you're curious, but it will be very useful after the tutorial when you're ready to create your own maps. There are also some handy cheat codes in there that might be fun to play with! To enter cheat codes in Retro Flight v2, you'll need to swipe the messages on the front page till you see one encouraging you to share the game with friends, then tap that message to get to the screen that asks you who told you about the game - that's the page where you enter the cheat codes.

You can edit the other author information if you like, but be careful about editing these files. Just one comma out of place and your phone won't be able to understand the JSON, so the game won't be able to use it.

Whenever you want to check your updated map still works, just upload it to the app again. Retro Flight is programmed to watch out for various mistakes you might make in the map files, and give you a useful warning so you have an idea of what it is you need to fix.

If it says it's not valid JSON, I recommend using a JSON parser to check where the problem is. Here are some online JSON parsers that seem to work fine. Many others are available, but I found some of them hung my browser when I tried to parse a large map with them.

http://jsonviewer.stack.hu/

http://jsonformatter.curiousconcept.com/

http://www.jsoneditoronline.org/

    Cluster instances

Every object in the game, such as a car or a tree, is represented by something I called a "cluster". Don't worry too much about this word, it was chosen because of some complexities in the app that you don't need to know about right now! Just remember that all the things in the world are represented in the map file by something called a cluster.

A cluster can also represent a *collection* of things. These types of clusters have other clusters within them, called subclusters. For example, in some maps there is a cluster type called "Park" that contains (among other things) many clusters called "Tree", so that means that the park will have lots of trees inside it.

Have a look at EmptyMap.json. It has 4 "Sea" clusters, an "Undersea" and an "Underland". (Cluster types always start with a capital letter). These make up the scenery, and you don't need to change them unless you want to make the map bigger or smaller.

It also has a cluster called "LockonBox". This is the yellow box that appears around a target when the player locks onto it. It's normally hidden, but we need it to exist, so leave this where it is.

The last cluster is the "Valkyrie" that the player is in, and it has a single subcluster called "RoflShadow" that follows it around, representing it's shadow on the floor. (It's named from when there was only one vehicle in the game, called "Roflcopter". If you ever look at some of the early screenshots of the game you'll see why!)

Let's put the player on the opposite team to the one they play on by default. Find the line that says...

"isPlayer" : true,

...and on the next line, type the following, exactly:

"onRedTeam" : true,

This changes which side that vehicle is on. But wait, because it's the player's vehicle we changed, we also need to change the metadata to reflect that the player has switched sides. Scroll back to the metadata, next to "Player On Red Team", change the word false to true. As this is a boolean (true or false) value, rather than a text value, it should not have quotes around it, but you will need the comma at the end!

Now if you were to run this new map on the device, the player's helicopter would have changed from desert colours to forest colours. If you had changed the metadata without the vehicle, or vice-versa, then the game would not have known where to put the player, and when you tried to play you would have had an out-of-body experience!

Let's change the player some more. Replace the word "Valkyrie" with "Saucer", run the game and see what happens. (Always make sure you get the capitalization right - it's Saucer, not saucer!)

This works just by changing the name, because a Saucer is normally about the same size as a Valkyrie, and works the same way as far as the cluster instance values are concerned. Sometimes, you won't be able to change one kind of cluster into another just by changing the name, you'll need to change other things too, like it's size, and maybe move it somewhere else.

    Turning stuff around

Just above the "clusterType" line you just changed, try adding the following line...

"yaw" : 180

...then see what happens when you run the game.

What just happened?

Some cluster instances will have values for "yaw", "pitch" and "roll".

Picture yourself in an airplane:

Yaw is turning right or left

Pitch is turning up or down

Roll is dipping one wing or the other

They are in degrees, so something with "yaw" of 180 will be facing backwards from where it would be by default, because you turned the object all the way around.

Here's the Wikipedia page about Yaw, Pitch and Roll.

    3D Co-ordinates

Before we can finish the map, we need to talk serious 3D math for a bit. Please bear with me, we'll be back changing the map files soon.

One-minute video intro

Each cluster's position in space is stored as X, Y, Z co-ordinates. Retro Flight uses the right-handed co-ordinate system (the one on the right in the diagram below). So...

X is negative on the left, and positive on the right.

Y is negative on the bottom, and positive on the top.

Z is negative at the front, and positive at the back.

Please note, though, that in the custom maps, the island object faces South. So...

X is negative going East, and positive going West.

Y is negative going down, and positive going up.

Z is negative going South, and positive going North.

You don't have to remember this right now, but it's worth checking later if you ever get confused about which way is which. I sometimes do!

    How big is your cluster?

Each cluster has something called a joint, which is where it connects to the coordinate system of it's parent. This is usually in the middle of the cluster, and it's the point around which it rotates if you turn it round. If it's parent moves around the map, the joint will follow that parent, keeping the child cluster connected to the parent.

The cluster's joint is expressed using 3 numbers: jointX, jointY, jointZ. This is it's 3D position, relative to the joint of the parent cluster. For top level clusters, it's relative to the middle of the map.

To express the cluster's size, you have 6 more numbers: startX, endX, startY, endY, startZ and endZ. These are the boundaries of the cluster, relative to the joint. The farther the values are from each-other, the larger the object. So if a cluster has a startZ of -2 (minus two) and endZ of 2, then startZ and endZ are 4 apart so the cluster will be 4 metres high. If it has a jointZ of 3, then it will also be standing one metre above the ground.

Sometimes these values are missing from the map file. If this happens, they'll default to zero, so you don't have to put every value into the map file, if it will just be zero, you can leave it out and the game will know what you intended.

    Things to watch out for with 3D co-ordinates...

The startX, startY and startZ values must always be less than or equal to their respective endX, endY, endZ values. So if you say that startX is +10 and endX is -10, the app will tell you off for getting them back-to-front.

Be careful to make sure that all subclusters are completely within the bounds of their parent clusters. If they're not, then they won't be solid objects, because the collision detection check is done on the parent cluster before the clusters inside it are checked.

Some clusters only work well as a particular size, or in a particular place relative to their parent or neighbours. If you want to know a good size for a cluster, or a good position for it relative to other clusters, have a look in one of the custom map files for where that cluster has been successfully used before, and use those values as a starting point.

That's the math out of the way, let's finish changing that map file...

    Let's finish the map!

In a normal game, you can only have four on each team. With map games, there is no such limit! The Saucer packs a heck of a punch, so let's send a dozen black helicopters to fight it.

Get the map SandboxInAirfield.json and search it for "Hawk"

This is the data for the black helicopter that sits on the airfield in a normal sandbox game. You'll notice that the cluster's data is in a strange order, but this won't matter. As long as the objects are nested properly so that they have the right parents and children, and that they're formatted properly so that the brackets and punctuation are correct, Apple's code doesn't care what order the lines of JSON are in, and it outputs it in a haphazard order. I edited EmptyMap.json myself to put the data in an order that would be easier to read.

We want to copy this Hawk cluster out of that map, and paste it into yours. You see that open-curly bracket a few lines above the word "Hawk"? Check for the close-curly bracket below it that matches it. Now, select all the text from the open curly bracket above, to the comma after the matching curly bracket below - this will include the "RoflShadow" subcluster in the middle - and copy all that text.

Now go into your own map, and paste that text you just copied (with it's Hawk and it's RoflShadow) to it's new home between the LockonBox cluster and the Saucer cluster in your own map file. There must also be a comma between the curly brackets of each cluster. Copied to your new map, it should look like this:

Notice the "mobileVeto" line above the word "Hawk". This tells the game that even though the Hawk is normally mobile, it should not move around in that map. That was because, on the other map, it was just supposed to wait on the airfield for the player to come and fly it. But in your new map, we *do* want it to move around and attack the player, so remove that "mobileVeto" line. Remove the whole line, not just the one word.

We should also start it a little higher above the sea, so it won't fall in the water and die. Set it's jointY to 5.0, and don't forget it needs a comma at the end of the line.

We don't need to care about moving it's RoflShadow, this shadow will move itself when the game is running. As long as it's the right size, and it's the subcluster of the Hawk, the shadow will be fine.

Now if you play with your new map, there will be a single black helicopter sneaking up to attack your UFO.

We want twelve helicopters, not just one! Select all the new cluster data for that Hawk, everything from the curly bracket above, to the comma after the matching curly bracket below, and copy. Then paste it till you have twelve of them, one beneath the other, all separated by a comma.

But, wait - all those Hawks are in the same place! Let's fix that. Change the jointX value of each Hawk to a different value. Change the first Hawk's jointX to be 100, then the next one 200, and so on, all the way to 1200 for the last one. Do NOT put a comma after the thousands digit, you will confuse the JSON if you do. Say 1200 rather than 1,200.

Later you may want to spread the helicopters out more at the start and put them on both sides of the player, but I'll leave that as an exercise for you to figure out if you feel like doing that. Hint: you'd need to change jointZ and jointX for each Hawk.

If you play the map, there should now be 12 Hawks fighting you, but there's still a problem. No-one can respawn after they die! That's because choppers respawn at Helipads, and there aren't any Helipads!

By now, you know what to do. Go search one of the custom maps for "Helipad", copy the code for that cluster into your map, and put it somewhere sensible by changing the jointX, jointY and jointZ values. Have at least two of them for each team. You remember how to change a cluster's team, don't you?

And that's it! You just made a fun new map out of an empty one, and with a bit of practice you'll be able to make new maps fairly quickly.

    Making your own maps

Here's the map making reference guide again. Keep this handy. You should also learn about JSON if you haven't already - see the links at the top of the page.

Different types of clusters need to be used in different ways. To make a working map, you'll need to look at how the clusters you want to use are used in the existing sample maps, or in other people's maps.

The "Empty Canvas" map is a simple one to start playing around with. I suggest you make your own copy of this, put that copy on the internet somewhere that it can be downloaded from, and download it in app, via the maps slider on the options menu. It should load a fairly empty map with just a helicopter controlled by the player.

Now you can paste in bits from other sample maps, edit it, and play around till you get the hang of things, loading your new creations in the app as you go. Be careful that you get the commas right, as this is a common mistake.

Before uploading a map, I recommend using a JSON parser to check that it's valid JSON. Here's a reminded of those online JSON parsers I showed you earlier.

http://jsonviewer.stack.hu/

http://jsonformatter.curiousconcept.com/

http://www.jsoneditoronline.org/

The Retro Flight app has been programmed to watch out for various mistakes you might make in the map files, and give you a useful warning so you have an idea of what it is you need to fix.

Please let me know if anything you do in a map crashes the game. Nothing, however messed up, should be able to actually crash the app. You should at least be able to quit out to the menu.

    Think you've made a good map?

Please test it lots as it probably has bugs in that you didn't think of.

If you have something good, don't forget to let the rest of us know so we can play with it too!

Thanks for listening. If you have any feedback or suggestions, you know where to find me.

Have fun,

Mike.