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
.