Most games work best when you have more than one level, but ip until now that's all I've had - one level. Even worse, that level has been created directly from code written into the game itself - to change it I have to rewrite the code. What I need is data driven level loading - the levels should be defined by a data file.
In this post I will be defining a level format and writing code to load it into the game. Let's start by talking about how the data will be laid out..
Level Data
I'm going to be loading the levels from JavaScript objects. I started off my defining what I wanted a level's data to look like:
Hopefully that's pretty easy to understand. There's some meta-data about the level itself (name, etc.), a type, a version and then a list of objects. The type just makes it easy for me to check that I'm looking at the right kind of data, and the version means that if I make changes to the data format in the future I can detect old versions and handle them appropriately - probably by upgrading them. The main part of the level data is the objects list. Inside this list you can see an array for each type of game object that can be loaded: player, spawners and zappers. Bullets aren't included as objects that I want to load, so they're missing from this list. Inside each of these object lists is an array of object data, and each entry in that array includes entries for all of the objects properties. This data is the configuration for each individual object and is passed to the object's constructor.
The code to load all of these objects into the Object Manager is pretty simple. I walk through the list of object types, going inside each list and pulling out the configuration object inside and using them as arguments to construct new objects of that type:
Validation With Schema
When it comes to loading user generated data, you absolutely need to be able to validate it before you use it - you simply cannot trust data that comes from outside of your control, you should even be pretty careful about data that you do control. I'm going to load the data as JavaScript objects, so the easiest way to validate it is by using a JSON schema. Creating a JSON schema is a fairly tricksy topic, so I won't go into it in depth here, but suffice it to say that you can define what your data format looks like in a schema (what properties it has, what the allowable values are, etc.) and then use that to validate data against. Data will either pass the validation check, and then you can trust it, or it doesn't.. and then you can't. In the game, users will be able to edit levels via an in-game editor. This should guarantee that the data is always in the correct format anyway, but it's safest to not rule out that someone may somehow manage to upload tainted level data, or maybe just in an older format. I need to be able to spot such bad data and handle it.
Just for "fun", here's what the JSON schema for a level looks like:
This looks fairly complex - and it is. You might guess that it's hard to create such a schema - it is. Luckily, the code generates most the schema for me. I added a function to each object type to retrieve the properties from each object type. Here's the zapper's function:
A neat by-product of this is that I can define default values for each of these properties, then I can automatically generate a default config for each object type. This will come in handy when it comes to creating new objects in the level editor.
A neat by-product of this is that I can define default values for each of these properties, then I can automatically generate a default config for each object type. This will come in handy when it comes to creating new objects in the level editor.
Validating Data Against The Schema
If defining the schema is hard, validating your data against it is even harder. Luckily, since JSON schema is quite popular there are some good libraries around to handle this for you. I settled on using the JSEN library - it's easy to integrate with my code and it's easy to use. Here's how I use it in the level loading code:
You can find out more about JSEN here.
Wrapping Up
I defined a level format, used a schema to validate levels against this schema and wrote code to load levels into the game.
The full code is here and the game can be played online here.
The full code is here and the game can be played online here.
Next Time
Now that I have a well-defined level format and I can load levels from data rather than hard-coding them in the main code, I'm one big step closer to letting players create their own levels. Next time I'll start on some simple editing tasks - maybe just selecting and moving existing items with the mouse. If it's not too much work then I will add saving too, otherwise that can wait until a future post.
Comments
Post a Comment