Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] New architecture for level serialization. #64

Open
dnesov opened this issue Nov 28, 2021 · 6 comments
Open

[Proposal] New architecture for level serialization. #64

dnesov opened this issue Nov 28, 2021 · 6 comments
Labels
enhancement New feature or request

Comments

@dnesov
Copy link

dnesov commented Nov 28, 2021

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.

@dnesov dnesov added the enhancement New feature or request label Nov 28, 2021
@iliasHDZ
Copy link

that's neat

@TechStudent10
Copy link

This approach is very clean. With the reboot of the project (I think) with the recent commits to gdext/app, I think this is the serialization method used there.

cc. @gducrash

@gducrash
Copy link
Contributor

Hi, yes, I plan to redo the level loading and saving systems, and this includes serialization as well. If you want to see the development process or help with it yourself, you can check us out on Discord

@TechStudent10
Copy link

Hi, yes, I plan to redo the level loading and saving systems, and this includes serialization as well. If you want to see the development process or help with it yourself, you can check us out on Discord

Eh I don't use Discord but would love to help with the development!

@gducrash
Copy link
Contributor

We do a lot of coordination-related stuff on Discord, since it's easier to communicate there casually. However, if you have something specific in mind that you want to add, fix or improve, you are welcome to use the issues tab to submit proposals and, after approvals, implement them.

@TechStudent10
Copy link

We do a lot of coordination-related stuff on Discord, since it's easier to communicate there casually. However, if you have something specific in mind that you want to add, fix or improve, you are welcome to use the issues tab to submit proposals and, after approvals, implement them.

Will do 👍🏾

@gducrash gducrash moved this to ⚪ Todo in Task Tracker: GDExt App Jan 2, 2023
@gducrash gducrash moved this from ⚪ Todo to 🟡 In Progress in Task Tracker: GDExt App Jan 2, 2023
@gducrash gducrash moved this from 🟡 In Progress to ⚪ Todo in Task Tracker: GDExt App Jan 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Todo
Development

No branches or pull requests

4 participants