-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathECS
More file actions
145 lines (120 loc) · 4.37 KB
/
ECS
File metadata and controls
145 lines (120 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
local Nocturne = {}
local Maid = require(game.ReplicatedStorage.Maid)
local Signal = require(game.ReplicatedStorage.Signal)
-- Storage for all entities, components, classes, and systems
Nocturne.entities = {}
Nocturne.components = {}
Nocturne.classes = {}
Nocturne.systems = {}
-- API: Register a new component class with default properties
function Nocturne.defineComponent(className, defaults)
Nocturne.classes[className] = defaults
end
-- API: Create a new entity with an optional list of components
function Nocturne.newEntity(components)
local entity = setmetatable({}, { __index = Nocturne.Entity })
entity.id = #Nocturne.entities + 1
entity.components = {}
entity.maid = Maid.new()
entity.signals = { OnDestroy = Signal.new() }
-- Initialize with provided components
if components then
for className, values in pairs(components) do
entity:addComponent(className, values)
end
end
Nocturne.entities[entity.id] = entity
return entity
end
-- Entity object and API
Nocturne.Entity = {}
-- Add a component to an entity
function Nocturne.Entity:addComponent(className, values)
local classTemplate = Nocturne.classes[className]
if not classTemplate then
error("Component class '" .. className .. "' is not defined.")
end
-- Initialize component based on its default template
local component = {}
for key, default in pairs(classTemplate) do
component[key] = values and values[key] or default
end
-- Component lifecycle signals
local signals = {
OnAdded = Signal.new(),
OnUpdate = Signal.new(),
OnRemoved = Signal.new()
}
component.signals = signals
-- Store the component and trigger the OnAdded event
self.components[className] = component
Nocturne.components[className] = Nocturne.components[className] or {}
Nocturne.components[className][self.id] = component
signals.OnAdded:Fire(self, component)
return component
end
-- Remove a component from an entity
function Nocturne.Entity:removeComponent(className)
local component = self.components[className]
if component then
local signals = component.signals
signals.OnRemoved:Fire(self, component)
-- Cleanup and remove component from system
signals.OnRemoved:Destroy()
signals.OnUpdate:Destroy()
signals.OnAdded:Destroy()
Nocturne.components[className][self.id] = nil
self.components[className] = nil
end
end
-- Retrieve a component from the entity
function Nocturne.Entity:getComponent(className)
return self.components[className]
end
-- API: Destroy an entity, clean up components, and fire OnDestroy signal
function Nocturne.Entity:destroy()
for className, _ in pairs(self.components) do
self:removeComponent(className)
end
self.signals.OnDestroy:Fire()
self.maid:DoCleaning()
Nocturne.entities[self.id] = nil
end
-- API: Define and register a system
function Nocturne.registerSystem(name, className, updateFunc)
Nocturne.systems[name] = { className = className, updateFunc = updateFunc }
end
-- API: Run all registered systems
function Nocturne.runSystems()
for _, system in pairs(Nocturne.systems) do
local className, updateFunc = system.className, system.updateFunc
for entityId, component in pairs(Nocturne.components[className] or {}) do
local entity = Nocturne.entities[entityId]
updateFunc(entity, component)
if component.signals.OnUpdate then
component.signals.OnUpdate:Fire()
end
end
end
end
-- Helper: Retrieve all entities with a specific component
function Nocturne.getEntitiesByComponent(className)
local entities = {}
for entityId, _ in pairs(Nocturne.components[className] or {}) do
table.insert(entities, Nocturne.entities[entityId])
end
return entities
end
return entities
-- Define a new component type for "Position"
Nocturne.defineComponent("Position", { x = 0, y = 0 })
-- Define a simple movement system
Nocturne.registerSystem("MoveSystem", "Position", function(entity, component)
component.x = component.x + 1 -- Move right
print("Entity", entity.id, "new position:", component.x, component.y)
end)
-- Create an entity with a Position component
local entity = Nocturne.newEntity({
Position = { x = 10, y = 20 }
})
Nocturne.runAllSyatems()