Username:
Password:
Login Register Password Lost

How to start developing with the engine

To develop the engine you will need to clone the GITHUB repository, and have at least a MySQL or MariaDB installed as well as NodeJS. Development of both the backend and the frontend is done using TypeScript. Never modify the JS files directly.

Front end development

Most of the work is only on the frontent as the backend is there mainly to keep the state of the game and players.
Inside the "public" directory (which is the directory served by NodeJS once you start the server), you will see an "Engine" directory which is the source code for the front end.

Add a new zone generator

The tasks involved to create a new generator are:
  1. Create a new file inside "public/Engine/Logic/WorldGenerators" called "CheckBoardGenerator.ts"
  2. Copy the content of "ConstantGenerator.ts" into the new file
  3. Change the class name to "CheckBoardGenerator"
  4. Add a new interface for the data needed by your generator
  5. Change the "DefaultParameters" and the "DisplayParameters" functions to reflect your needs for the parameters specific to your generator
  6. Finally change the "Generate" function to generate the zone as expected
The whole code for the CheckBoard generator can be found here:
/// <reference path="WorldGenerator.ts" />

interface CheckBoardData
{
    oddTile: string;
}

@WorldGeneratorClass
class CheckBoardGenerator extends WorldGenerator
{
    constructor(world: World, seed: string, zoneInfo: WorldZone)
    {
        super(world, seed, zoneInfo);
    }

    public Generate(x: number, y: number, zone: string): WorldArea
    {
        var worldArea = new WorldArea();
        worldArea.X = x;
        worldArea.Y = y;
        worldArea.Zone = zone;
        worldArea.world = this.world;

        worldArea.backgroundTiles = [];
        worldArea.objects = [];

        var checkboardData = this.zoneInfo.GeneratorParameters;

        // Fill the world with the background
        for (var a = 0; a < this.world.areaWidth; a++)
        {
            var type: number[];

            for (var b = 0; b < this.world.areaHeight; b++)
            {
                if ((Math.floor(a / 4) + Math.floor(b / 4)) % 2 == 0)
                    type = this.world.art.background.types[this.zoneInfo.BaseTileType];
                else
                    type = this.world.art.background.types[checkboardData.oddTile];
                worldArea.backgroundTiles[a + b * this.world.areaWidth] = type[Math.floor(this.rnd.Next() * type.length)];
            }
        }

        this.GenerateObjects(worldArea);
        worldArea.RecoverActors();
        return worldArea;
    }

    public GetBaseBackgroundTile(x: number, y: number, areaX: number, areaY: number, zone: string): number
    {
        try
        {
            if (!this.world.art.background.types[this.zoneInfo.BaseTileType])
                this.world.art.background.types[FirstItem(this.world.art.background.types)][0];
            return this.world.art.background.types[this.zoneInfo.BaseTileType][0];
        }
        catch (ex)
        {
            return 0;
        }
    }

    public static DefaultParameters(): CheckBoardData
    {
        var knownTypes = Keys(world.art.background.types);
        return { oddTile: (knownTypes.length > 1 ? knownTypes[1] : knownTypes[0]) };
    }

    public static DisplayParameters(generatorParameters: CheckBoardData): string
    {
        var html = "";
        html += "<tr><td>Walkable Tile:</td>";
        html += "<td><select onchange='MazeGenerator.ChangeParameter(\"oddTile\")' id='oddTile'>";
        for (var j in world.art.background.types)
            html += "<option value='" + j + "'" + (generatorParameters.oddTile == j ? " selected" : "") + ">" + j + "</option>";
        html += "</select></td></tr>";
        return html;
    }

    public RenameTileType(oldName: string, newName: string)
    {
    }
}
The "DisplayParameters" function is used to include the needed parameters of the new generator within the editor, while the "DefaultParameters" function will instead produce the object with the default values.

The function "Generate" is where all the magic happens. While in this example we kept the function relatively simple, it's possible to have complex generators creating procedural maps. Keep in mind however that those generators will be called for each map cell the player will visit, and therefore needs to be relatively fast. The "x" and "y" variables received are the coordinates within the cell, and the areaX and areaY are the coordinate of the cell. You can get an absolute coordinate by doing the following operation: (areaX * this.world.areaWidth + x) and (area> * this.world.areaHeight + y).

As any engine development, you will need to ensure the code is compiled from TypeScript to JS. You can either manually invoke: "gulp compile:client" from a command line within the server directory or use the gulp without arguments to let it watch any change while you edit your files.

As soon as the new file is compiled, you will be able to test it within the engine in the "Editors" => "Zones" editor, which should offer now a new type of generator called "CheckBoard".

Add a new function to the in game scripting

The tasks involved to create a new script function are:
  1. Create a new file inside "public/Engine/Logic/Parser/EngineAPI" called "EngineSimpleFunctions.ts"
  2. Define a new class with the tag "@ApiClass" in front
  3. Define a new function with the tag "@ApiMethod" and follow the correct signature
The whole code for the CheckBoard generator can be found here:
/// <reference path="../CodeEnvironement.ts" />

@ApiClass
class EngineSimpleFunctions
{

    @ApiMethod([{ name: "valueA", description: "The first value to add." }, { name: "valueB", description: "The second value to add." }], "Adds to values together.")
    AddValues(values: VariableValue[], env: CodeEnvironement): VariableValue
    {
        if (values[0] === null || values[1] == null)
            return null;
        return new VariableValue(values[0].Value + values[1].Value);
    }
}
Again you must compile the Typescript code, and then you will be able to use your newly define function within any in game script. The "@ApiMethod" tag allows to have documentation about your function which is both visible within the editor as well as the API documentation.

© 2016 - 2019 - A. Bertrand - Terms & conditions