8000 [Proposal] New architecture for level serialization. · Issue #64 · gdext/editor · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
[Proposal] New architecture for level serialization. #64
Open
@dnesov

Description

@dnesov

Problem

The current code for level serialization is messy and not comfortable to use (involves a lot of hacks and tricks, see levelparse.js) and doesn't allow for extension (if a new game version will release, we would have to go through a lot of steps to adapt for the new content).

Solution

I propose a cleaner architecture that benefits from the use of TypeScript that can be easily extended and composed, if needed (GD's level format involves a lot of composition, for example trigger properties). The idea is to implement an abstract GDObject class that has GDProperty inherited properties (Vector2, ZLayer) as well as serialize() abstract method.

GDObject

As mentioned previously, GDObject is an abstract class with ZLayer and Vector2 fields and an abstract serialize() method. This is how it could look in TypeScript code:

abstract class GDObject {
    public position: Vector2;
    public zLayer: ZLayer;

    public constructor(position: Vector2, zLayer: ZLayer) {
        this.position = position;
        this.zLayer = zLayer;
    }
    abstract serialize(): string;
}

Then, it gets inherited by GDBlock and GDTrigger classes that implement the abstract serialize() method, that will be explained later.

GDProperty

Just like GDObject, GDProperty is an abstract class, but it only defines a single abstract serialize() method.
Here's how it can look in code:

abstract class GDProperty {
    abstract serialize(): string;
}

As mentioned previously, Vector2 and ZLayer classes extend a GDProperty, and are used as properties of GDObject.

Vector2

Pretty obvious, its a two component structure with X and Y coordinates. This is how it can be implemented:

class Vector2 extends GDProperty {
    public x: number;
    public y: number;

    public constructor(x: number, y: number) {
        super();

        this.x = x;
        this.y = y;
    }
    serialize(): string {
        // do the actual serialization to the GD key/value format.
        return "";
    }
}

It can also implement other methods, for example dot() or length(), if we will need them.

ZLayer

Again, its in the name. It only contains a number value index:

class ZLayer extends GDProperty {
    public index: number;

    public constructor(index: number) {
        super();
        this.index = index;
    }
    
    serialize(): string {
        // do the actual serialization to the GD key/value format.
        return "";
    }
}

And so on, for every property type we'd like to have.

GDTrigger

Triggers are interesting ones as OOP approach will render them pretty messy. This is why I think we could compose GDProperty together in a properties array.

class GDTrigger extends GDObject {
    private properties: GDProperty[];

    public constructor(position: Vector2) {
        super(position);
    }

    public addProperty(property: GDProperty) {
        this.properties.push(property);
    }

    serialize(): string {
        let result: string;

        this.properties.forEach(property => {
            result += property.serialize();
        });

        return result;
    }
}

GDBlock

Extends GDObject but adds properties like color, etc. needed for a block.

In practice

In the actual editor backend the level will look like an array of GDObject, and when its time to save the level in GD's format it will be pretty easy to do so:

function serializeLevel(): void {
    let result: string;

    objects.forEach(object => {
        result += object.serialize();
    });
}

Benefits

With this approach, its trivial to add more types of objects and properties, resulting in much cleaner code. However, we should also consider that level format might change, so we should somehow combat that as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    ⚪ Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0