3
\$\begingroup\$

I made a game a year ago featuring a custom scripting language, but I realised that it took far too long to actually make the language and there were many commands that were very rarely used.

I'm trying now to do something similar with a game I'm working on, and I'm wondering what the simplest way to store level data would be. There are programs like Tiled that let you store some JSON data and tiles and .png's and whatnot, but I want to be able to store commands for what happens within a level gameplay wise. I'll give some examples.

I could have a file for the starting room that has commands that run when you enter the room, e.g. to have some text pop up, have a character walk up to the player, etc. I could also have individual commands for what happens when you interact with an object or with a character. What's a good way to store this data without having to write my own scripting language? It's not too difficult to make a very basic one with minimal functionality, but I feel like there are much better ways out there.

\$\endgroup\$
  • 1
    \$\begingroup\$ Every single engine I've ever used does this differently. If there were just one "best" or "simplest" way, we'd expect to see more consensus here. So I don't recommend holding out for one "ideal" method. Take what you have that almost works, and ask for ways to close the gap. Say you can store JSON data with your tiles? Great, store JSON lists of commands/events. If that doesn't serve your needs, edit your question to explain what you need help doing beyond that. \$\endgroup\$ – DMGregory Jun 28 at 19:58
2
\$\begingroup\$

There are fundamentally two parts to anything in a video game; data and behaviour.

An example of data would be the speed of the player, how high they can jump, how many enemies should spawn in a certain room, etc.

An example of behaviour would be that the player jumps when SPACEBAR is pressed, the enemies spawn when the player picks up the golden coin in the room, and that there should be a cut-scene when all the enemies are dead.

The reason I mention the difference is because you are approaching this problem in the wrong way. A data file (json, xml, ini, etc.) does NOT store behaviour! Storing behaviour is the role of a programming language! Or in your case a scripting languages that the main program can interpret at runtime. This means your previous approach of a custom scripting language was actually correct (except for the "custom" part. Use an already existing one)!

Luckily for you a programming language quite neatly doubles as a way to store data, so I would recommend to store your maps in the programming language as well. Personally I use Java as my "main" language, JavaScript as my scripting language (for behaviour) and Json as my data storage language (since it couples nicely with JavaScript). A map file in my game looks something like this:

// P.S. this is TypeScript that I transpile (convert) into JavaScript.
// Highly recommended if you want typing in your scripting language!
const spriteSheetPath = "my_sprite_sheet.png";
preloadAsset(spriteSheetPath, "Texture");

const grassTexture = texture(spriteSheetPath, { x: 5, y: 0, w: 16, h: 16, margin: 1 });
const grass = tile(grassTexture);

const bushTexture = texture(spriteSheetPath, { x: 19, y: 9, w: 16, h: 16, margin: 1 });
const bush = interactive(tile(bushTexture), (entity) => {
    // Function is called when an entity interacts with this bush
    // Give the entity 1-4 berries
    entity.inventory.add(ItemAtlas.create("berry", Math.random(1, 4)));
});

function layout(): TileOrAlias[][][] {
    return [
        [ // Layer 1
            [2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        ],
        [ // Layer 2
            ...
        ]
    ];
}

function map(): GameMap {
    const width = 10;
    const height = 10;
    const noAliasLayout = replaceAliases(layout(), {
        1: grass,
        2: bush
    });
    const navGrid = generateNavgrid(noAliasLayout, width, height);

    return {
        width,
        height,
        layout: noAliasLayout,
        navGrid
    };
}
map;

I would then run this file from my main language, call the map function that is returned by the file, and convert the data that is returned from it into a Map object that my main language can interact with!

P.S. Like I said above I would definitely not create your own scripting language! Use an already existing one such as JavaScript, Lua, or Python.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you for the response! This is very helpful, I just have some questions. First off, I have tried using Lua before as a scripting language with no luck. With Javascript or Python I would be able to store behavior as well, right? Does that mean I could have a script with a function e.g. text("test"), that would run code directly from the programming language of my game (C++)? Would I be able to pause the script after each line? I'm sorry to be asking so many questions, I am just having a hard time finding good resources on the subject. \$\endgroup\$ – Apollo Johnson Jun 28 at 21:14
  • \$\begingroup\$ @ApolloJohnson Of course, you can do anything from a scripting language that you can do from any other programming language. For an example of behaviour check the bush object in my code example, it is of type interactive and will call the function I supplied ((entity) => { /* code */ }) when it is interacted with. Any library that can parse a scripting language should be able to "inject" variables from your main language into your scripting language too, e.g. a text function that displays some text on the screen. As for pausing after every line that depends on the library you are using \$\endgroup\$ – Charanor Jun 28 at 21:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.