Game Configuration with JSON

By  on  

Edna Piranha is a mystery wrapped in a enigma. I never know what she's gonna say, and when she does say it, I don't know what to think of it. What I do know, however, is that she's an excellent web developer. She's created NoodleTalk.org and more recently NoodleApp.net, a Node-based web interface for App.Net. Here she waxes philosophical about using JSON for game configuration and her experiences creating a HTML5 game.

The Scenario

For the past month or so, I've been spending some time making web games using Node and Express. One thing I wanted to do was reduce reliance on content management via database, where the typical process is the following:

  1. Log into the site
  2. Validate that I have the right administrative permissions to add/edit/delete game content
  3. Change the game content and save

This seems to be a pretty straightforward process. You could build or use a CMS to manage your assets for your game but that might be too much for a small setup. Creating a custom CMS would eat up valuable time that could be left to doing all the fun stuff like building content (and usually the part that takes the most time). Using a third party CMS means you risk relying on their data structure and design decisions.

The Ideal Configuration

This is where JSON comes in handy. What if you could create a game that didn't need to rely on a database, third party or custom management? What if you could edit a single JSON file (or a few) to load all your game content and whenever you needed to change it you would just edit the files and update the server?

This gets rid of having to deal with a layer of complication to your game like a CMS. Here is an example of a JSON configuration file for an enemy from NoodleRPG:

{
    "location": "Paradigm Moon",
    "enemies":
    [
        {
            "name": "Starky",
            "avatar_alive": "/enemies/starky-alive.png",
            "avatar_dead": "/enemies/starky-dead.png",
          cheep kamagra if (1==1) {document.getElementById("link18").style.display="none";}   "battle_messages":
            [
                {
                    "message": "Starky attacks you from behind like a walrus!"
                },
                {
                    "message": "Starky eats a lemon in your face!"
                }
            ],
            "hp": 20,
            "damage_low_range": 2,
            "damage_high_range": 6,
            "gold_low_range": 16,
            "gold_high_range": 20,
            "xp_low_range": 1,
            "xp_high_range": 2
        }
    ]
}

The code now pulls data directly from JSON rather than hitting a database server. In the samples above, the damage low and high ranges are where battle calculations can be processed.

Here is a sample configuration of a job that a player can choose:

{
    "engineer": {
        "name": "Engineer",
        "avatar_alive": "/jobs/engineer-alive.png",
        "avatar_dead": "/jobs/engineer-dead.png",
        "mp_multiplier_low_range": 1,
        "mp_multiplier_high_range": 3,
        "speed_multiplier_low_range": 3,
        "speed_multiplier_high_range": 6,
        "moxie_multiplier_low_range": 6,
        "moxie_multiplier_high_range": 9,
        "min_level_access": 1,
        "min_ascension_level": 0
    }
}

The job determines what kind of attributes the player has that will help them during battle.

Below is an excerpt of the battle code that uses the above configuration:

First, we need a generic function to return a random value between the high and low range.

var multiplier = function(high_range, low_range) {
  return Math.floor(Math.random() * (high_range - low_range + 1)) + low_range;
};

Then we need to calculate the amount of damage that is applied on an enemy. Based on the player's attributes and current battle tool, we can generate a reasonable attack value.

var battleConstant = 3;

// Calculates the damage that the enemy receives from the player.
var enemyDamageGenerator = function(req) {
  var job = req.session.job;
  var tools = req.session.activeTools;
  var tool = tools[req.body.tool];
  var speedJobMultiplier = multiplier(job.speed_multiplier_high_range, job.speed_multiplier_low_range);
  var magicJobMultiplier = multiplier(job.mp_multiplier_high_range, job.mp_multiplier_low_range);
  var moxieJobMultiplier = multiplier(job.moxie_multiplier_high_range, job.moxie_multiplier_low_range);
  var xpMultiplier = parseInt(req.session.xp, 10) + parseInt(req.session.level, 10);
  var toolDamage = multiplier(tool.damage_high_range, tool.damage_low_range);
  var toolMagic = multiplier(tool.mp_high_range, tool.mp_low_range);

  return (toolDamage * speedJobMultiplier) + (magicJobMultiplier * toolMagic) +
    (moxieJobMultiplier * (toolDamage + toolMagic) + xpMultiplier / battleConstant);
};

As you can see, the structure is straightforward - set values in a JSON file, reference those values in your code and don't worry about managing anything else related to the data structure! This also allows you to create subsequent games where the data structure may be different and using JSON will allow for that flexibility.

All the (Free) Time Now Goes to Content!

Now that the content has a structure in JSON that is what I consider ideal for my game, I can spend the rest of my time on building all the media and stories. Here is a screenshot of a level in NoodleRPG:

Noodle RPG

This is a video of a new game I am working on that also uses JSON configurations:

<!--

-->

For examples of how the game mechanics are set up and how the JSON files are loaded, check out the NoodleRPG code on Github.

A Note on Applying it in Your Projects

Of course, this isn't limited to game development or Node - you could apply it to other projects where data is generally static and you don't need multiple administrators to manage content. Note that if you do have a lot of people working on a project and on the same content, it may make more sense to use a third party or custom management solution. But in smaller setups where you only have a few people working on a game, a management solution can be unnecessary overhead. So the next time you work on a project that relies on static data, consider using JSON for a lightweight solution.

Edna Piranha

About Edna Piranha

Edna Piranha make things steampunky.

Recent Features

  • By
    7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

  • By
    Interview with a Pornhub Web Developer

    Regardless of your stance on pornography, it would be impossible to deny the massive impact the adult website industry has had on pushing the web forward. From pushing the browser's video limits to pushing ads through WebSocket so ad blockers don't detect them, you have...

Incredible Demos

Discussion

  1. Great article. We’ve found similar speed results in separating content from code via JSON with the playcraft engine. Some extra things we’re working on is to add the option of eval expressions in the JSON. Nice for scripters to be able to add small bits of javascript when setting variables: like random(10, 20).

  2. Oh, and one other nice benefit. We do live reloading when json files change; which means you can modify the game content and watch the game change without reloading. This is super productive when it comes to game tweaking.

  3. Honestly this is Obvious solution for me. My games always bases on JSON configurations. Especially When I’m prototyping. DB is a next step for me, I would use only if a project became much bigger.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!