1
+ options indenting = 2
2
+
3
+ options no_unused_block_arguments = false
4
+ options no_unused_function_arguments = false
5
+ options multiple_contexts
6
+ options strict_smart_pointers = true
7
+
8
+ struct EntityId {
9
+ id: uint;
10
+ }
11
+
12
+ let INVALID_ENTITY_ID = EntityId (id = 0xFFFFFFFFu );
13
+
14
+ def operator == (a : EntityId ; b : EntityId ): bool {
15
+ return a .id == b .id ;
16
+ }
17
+
18
+ def operator ! = (a : EntityId ; b : EntityId ): bool {
19
+ return a .id ! = b .id ;
20
+ }
21
+
22
+ struct Position {
23
+ x: float;
24
+ y: float;
25
+ }
26
+
27
+ struct Velocity {
28
+ dx: float;
29
+ dy: float;
30
+ }
31
+
32
+ struct Health {
33
+ current: int;
34
+ max: int;
35
+ }
36
+
37
+ let MAX_ENTITIES = 10 ;
38
+ var entity_id_counter : uint = 0u ;
39
+ var active_entities : int = 0 ;
40
+
41
+ var positions : array < Position > ;
42
+ var velocities : array < Velocity > ;
43
+ var healths : array < Health > ;
44
+
45
+ var has_position : array < bool > ;
46
+ var has_velocity : array < bool > ;
47
+ var has_health : array < bool > ;
48
+
49
+ def create_entity (): EntityId {
50
+ if (active_entities < MAX_ENTITIES ) {
51
+ let new_id = entity_id_counter ;
52
+ entity_id_counter ++ ;
53
+ var eid = EntityId (id = new_id );
54
+ let index = int (eid .id );
55
+
56
+ if (index > = length (has_position )) {
57
+ let new_size = index + 1 ;
58
+ if (length (positions ) < new_size ) resize (positions , new_size );
59
+ if (length (velocities ) < new_size ) resize (velocities , new_size );
60
+ if (length (healths ) < new_size ) resize (healths , new_size );
61
+ if (length (has_position ) < new_size ) resize (has_position , new_size );
62
+ if (length (has_velocity ) < new_size ) resize (has_velocity , new_size );
63
+ if (length (has_health ) < new_size ) resize (has_health , new_size );
64
+ }
65
+
66
+ has_position [index ] = false ;
67
+ has_velocity [index ] = false ;
68
+ has_health [index ] = false ;
69
+ active_entities ++ ;
70
+ return eid ;
71
+ } else {
72
+ return EntityId (id = INVALID_ENTITY_ID .id );
73
+ }
74
+ }
75
+
76
+ def add_position_component (eid: EntityId; comp: Position) {
77
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
78
+ let index = int (eid .id );
79
+ positions [index ] = comp ;
80
+ has_position [index ] = true ;
81
+ }
82
+ }
83
+
84
+ def add_velocity_component (eid: EntityId; comp: Velocity) {
85
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
86
+ let index = int (eid .id );
87
+ velocities [index ] = comp ;
88
+ has_velocity [index ] = true ;
89
+ }
90
+ }
91
+
92
+ def add_health_component (eid: EntityId; comp: Health) {
93
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
94
+ let index = int (eid .id );
95
+ healths [index ] = comp ;
96
+ has_health [index ] = true ;
97
+ }
98
+ }
99
+
100
+ def remove_position_component (eid: EntityId) {
101
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
102
+ has_position [int (eid.id)] = false ;
103
+ }
104
+ }
105
+
106
+ def remove_velocity_component (eid: EntityId) {
107
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
108
+ has_velocity [int (eid.id)] = false ;
109
+ }
110
+ }
111
+
112
+ def remove_health_component (eid: EntityId) {
113
+ if (eid ! = INVALID_ENTITY_ID && eid .id < entity_id_counter ) {
114
+ has_health [int (eid.id)] = false ;
115
+ }
116
+ }
117
+
118
+ def movement_system (dt: float) {
119
+ unsafe {
120
+ for (i_idx in range (0 , int (entity_id_counter ))) {
121
+ if (has_position [i_idx ] && has_velocity [i_idx ]) {
122
+ var pos : Position & = positions [i_idx ];
123
+ let vel : Velocity & = velocities [i_idx ];
124
+ pos .x + = vel .dx * dt ;
125
+ pos .y + = vel .dy * dt ;
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ def damage_system (damage_amount: int) {
132
+ unsafe {
133
+ for (i_idx in range (0 , int (entity_id_counter ))) {
134
+ if (has_health [i_idx ] && has_velocity [i_idx ]) {
135
+ var hp : Health & = healths [i_idx ];
136
+ hp .current - = damage_amount ;
137
+ if (hp .current < 0 ) {
138
+ hp .current = 0 ;
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ def cleanup_system () {
146
+ unsafe {
147
+ for (i_idx in range (0 , int (entity_id_counter ))) {
148
+ if (has_health [i_idx ]) {
149
+ let hp : Health & = healths [i_idx ];
150
+ if (hp .current < = 0 ) {
151
+ let current_eid = EntityId (id = uint (i_idx ));
152
+ print ("Entity { current_eid .id } has run out of health. Removing components.\n " );
153
+ remove_position_component (current_eid );
154
+ remove_velocity_component (current_eid );
155
+ remove_health_component (current_eid );
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ def print_entity_status_system () {
163
+ unsafe {
164
+ for (i_idx in range (0 , int (entity_id_counter ))) {
165
+ let current_eid = EntityId (id = uint (i_idx ));
166
+ var status_string = "Entity { current_eid .id } :" ;
167
+ var has_any_component_for_this_id = false ;
168
+
169
+ if (i_idx < length (has_position ) && has_position [i_idx ]) {
170
+ let pos : Position & = positions [i_idx ];
171
+ status_string + = " Pos({ pos .x } ,{ pos .y } )" ;
172
+ has_any_component_for_this_id = true ;
173
+ }
174
+ if (i_idx < length (has_velocity ) && has_velocity [i_idx ]) {
175
+ let vel : Velocity & = velocities [i_idx ];
176
+ status_string + = " Vel({ vel .dx } ,{ vel .dy } )" ;
177
+ has_any_component_for_this_id = true ;
178
+ }
179
+ if (i_idx < length (has_health ) && has_health [i_idx ]) {
180
+ let hp : Health & = healths [i_idx ];
181
+ status_string + = " HP({ hp .current } /{ hp .max } )" ;
182
+ has_any_component_for_this_id = true ;
183
+ }
184
+
185
+ if (has_any_component_for_this_id ) {
186
+ print ("{ status_string } \n " );
187
+ }
188
+ }
189
+ }
190
+ }
191
+
192
+ [export ]
193
+ def main () {
194
+ let e1 = create_entity ();
195
+ if (e1 ! = INVALID_ENTITY_ID ) {
196
+ add_position_component (e1 , Position (x = 0.0 , y = 0.0 ));
197
+ add_velocity_component (e1 , Velocity (dx = 1.0 , dy = 0.5 ));
198
+ add_health_component (e1 , Health (current = 100 , max = 100 ));
199
+ }
200
+
201
+ let e2 = create_entity ();
202
+ if (e2 ! = INVALID_ENTITY_ID ) {
203
+ add_position_component (e2 , Position (x = 10.0 , y = 5.0 ));
204
+ add_health_component (e2 , Health (current = 50 , max = 50 ));
205
+ }
206
+
207
+ let e3 = create_entity ();
208
+ if (e3 ! = INVALID_ENTITY_ID ) {
209
+ add_position_component (e3 , Position (x = - 5.0 , y = - 5.0 ));
210
+ add_velocity_component (e3 , Velocity (dx = - 0.2 , dy = 1.0 ));
211
+ add_health_component (e3 , Health (current = 75 , max = 75 ));
212
+ }
213
+
214
+ let time_step = 1.0 ;
215
+ let base_damage = 30 ;
216
+
217
+ for (i_step in range (0 , 5 )) {
218
+ print ("--- Simulation Step { i_step } ---\n " );
219
+ movement_system (time_step );
220
+ damage_system (base_damage );
221
+ cleanup_system ();
222
+ print_entity_status_system ();
223
+ if (i_step == 1 ) {
224
+ let e4 = create_entity ();
225
+ if (e4 ! = INVALID_ENTITY_ID ) {
226
+ print ("Adding new entity e4 (id { e4 .id } ) at step { i_step } \n " );
227
+ add_position_component (e4 , Position (x = 2.0 , y = 2.0 ));
228
+ add_velocity_component (e4 , Velocity (dx = 0.1 , dy = - 0.1 ));
229
+ add_health_component (e4 , Health (current = 120 , max = 120 ));
230
+ }
231
+ }
232
+ }
233
+ }
0 commit comments