chaos-lang / chaos

The Chaos Programming Language
https://chaos-lang.org
GNU General Public License v3.0
280 stars 17 forks source link

[RFC] Event-driven Entity Component System #85

Open mertyildiran opened 3 years ago

mertyildiran commented 3 years ago

Entity Component Systems (ECS) are widely used among game programmers since it's a data organization pattern that does not require inheritance unlike common Object-Oriented patterns but instead functionality is provided by the components.

We will going to implement ECS in Chaos as an alternative to common Object-Oriented Programming (OOP) paradigm with an event-driven approach. Such that entities will have components and be able to emit events. Components on the other hand, will be able to listen those events, all by using the language's syntax. Here are two examples to demonstrate the syntax and possible use cases:

Server-side data modeling:

import datetime
import string
import type

event StudentCreated

entity School
    has Students
end

component Students
    Student list students
    num student_count = 0

    void def add_student(Student student) listens StudentCreated
        array.insert(students, student)
        student_count++
    end

    num def get_student_count()
        return student_count
    end
end

entity Student
    has NameSurname
    has Age
    emits StudentCreated on create
end

component NameSurname
    str name
    str surname

    void def set_name_surname(str name, str surname)
        this.name = name
        this.surname = surname
    end

    str def get_fullname()
        str fullname = string.join([name, surname], ' ')
        return fullname
    end
end

component Age
    num age = 0
    str birth_date

    void def set_birth_date(str birth_date = '01.01.1950')
        str list = string.split(birth_date, '.')
        num year = type.num(list[2])
        this.age = datetime.year() - year
    end

    num def get_age()
        return this.age
    end
end

school = new School

student = new Student
print student.get_age() # Should print 0
student.set_name_surname('John', 'Doe')
student.set_birth_date('21.12.1984')
print student.get_fullname() # Should print 'John Doe'
print student.get_age() # Should print 36

print school.get_student_count() # Should print 1

Game programming:

import some_rendering_lib

event Redraw, Collision

entity Sphere
    has Radiality
    has Physics
    has Collider
    emits Collision on collide
    emits Redraw on set_coordinates
end

component Position
    num x
    num y
    num z

    void def draw() listens Redraw
        some_rendering_lib.translate(this)
    end
end

component Radiality
    num radius
end

component Physics
    requires Position
    num velocity

    void def apply_force(Collider collider) listens Collision
        num x = this.x + collider.force / 3 * collider.direction
        num y = this.y + collider.force / 3 * collider.direction
        num z = this.z + collider.force / 3 * collider.direction
        this.velocity++
        this.set_coordinates(x, y, z)
    end

    num list def get_coordinates()
        num list coordinates = [this.x, this.y, this.z]
        return coordinates
    end

    void def set_coordinates(num x, num y, num z)
        this.x = x
        this.y = y
        this.z = z
    end
end

component Collider
    num force
    num direction

    void def collide(entity other_thing, num force, num direction)
        this.force = force / 2
        this.direction = direction
        other_thing.collide(this.force, - this.direction)
    end
end

sphere1 = new Sphere
sphere1.x = 0
sphere1.y = 0
sphere1.z = 0
sphere1.radius = 1
sphere1.velocity = 0

sphere2 = new Sphere
sphere2.x = 2
sphere2.y = 2
sphere2.z = 2
sphere2.radius = 1
sphere2.velocity = 0

sphere1.collide(sphere2, 6, -1) # Triggers Collision event
print sphere1.get_coordinates() # Should print [-1, -1, -1]
print sphere2.get_coordinates() # Should print [3, 3, 3]

Note: create, read, update and delete functions will be available for emits X on Y syntax for every entity and those functions will be overridable.