forked from ceu-lang/ceu-sdl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
sim.ceu
341 lines (313 loc) · 9.04 KB
/
sim.ceu
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// - bug play no inicio
// - async vs async_ (testar async no jogo!)
// - tests para pause/async
// - outros jogos
// - blog:
// - replay
// - debug, na velocidade que quiser, seek, retomada em qq ponto
// - replay em jogo
// - simulacao
// - velocidade infinita para testes
// - controle de NPC com interface equivalente
// - após morte
// - single player
// - mecanica
// - exige 1st-class-time-machine
// - Como?
// - evento de proxy
// - start/stop
// - gravacao em tempo real
// - save/restore all state
// - ceu é estático, mesmo p/ instâncias dinâmicas
// - grava estado inteiro de X em X ms
// - entre intervalos, usa eventos gravados
// - teoricamente, só precisa dos eventos
input void SDL_QUIT_;
input int SDL_DT_;
input _SDL_KeyboardEvent* SDL_KEYDOWN_;
input _SDL_KeyboardEvent* SDL_KEYUP_;
#include "c.ceu"
#include "sdl.ceu"
native do
##include <time.h>
unsigned int* RAND_SEED;
#define drand() rand_r(RAND_SEED)
int TIME1 = 3;
int TIME2 = 3;
end
class App with
event int ok;
do
var uint seed = _time(null);
_RAND_SEED := &seed; // App is supposed to live until "sim" is alive
_srand(seed);
#define srand(x)
#define _SDL_RenderPresent(x) nothing
#define _Mix_PlayChannel(a,b,c) if not _CEU_TIMEMACHINE_ON then _Mix_PlayChannel(a,b,c); end
var int ret = do
#ifdef CEUFILE
#define _STRINGIFY(X) #X
#define STRINGIFY(X) _STRINGIFY(X)
#include STRINGIFY(CEUFILE)
#else
#include "main.ceu"
#endif
end;
emit this.ok => ret;
#undef _SDL_RenderPresent
#undef _Mix_PlayChannel
end
var App app;
/* The "Time Machine" must be declared after "The Application".
* The "tm" must record the events *after* the "app" reacts to them.
*/
#define TM_INPUT_DT SDL_DT
#define TM_INPUT_REDRAW SDL_REDRAW
//#define TM_DELAY(v) _SDL_Delay(v)
#if 0
#define TM_QUEUE
#define TM_QUEUE_N (10*60*60 * (2+8+32))
/* 10e/s for 1h */
/* sizeof(tceu_queue)=8
sizeof(SDL_KeyboardEvent)=32
*/
/*
// 60min*60sec*1000ms=(1h in ms)
// * minimum size of an event
// CEU_FPS * events/frame
// 1h of events with 2 events/frame
// 3600*1000 = 3600000 =>/30 = 120000 =>2 = 240000 = 240K events
*/
#define TM_QUEUE_WCLOCK_REUSE
#endif
#if 1
#define TM_DIFF
#define TM_DIFF_N 1000000000 // 1GB
#endif
#if 1
#define TM_SNAP
#if defined(TM_QUEUE) || defined(TM_DIFF)
#define TM_SNAP_MS 10000 /* [10000] 10s = 30*10 = at most 300 frames to traverse */
/* 0 means "do not take snaps" */
#endif
#define TM_SNAP_N 6*60 /* 10s*6*60=1h (360*56K-rocks = 1.8Mb) */
#endif
_printf("APP %ld\n", sizeof(_CEU_App));
_printf("KEY %ld\n", sizeof(_SDL_KeyboardEvent));
#include "timemachine.ceu"
#define _UITM_REN _REN
#include "ui-timemachine.ceu"
#ifdef TM_QUEUE
class IOTimeMachine with
interface IIOTimeMachine;
do
par do
loop do
// starts off
watching this.go_on do
par do
var _SDL_KeyboardEvent* key;
every key in SDL_KEYDOWN do
_queue_put(_CEU_IN_SDL_KEYDOWN,
sizeof(_SDL_KeyboardEvent), (byte*)key
#ifdef TM_SNAP
, 0
#endif
)
finalize with
nothing; // events are mem'copied
end;
end
with
var _SDL_KeyboardEvent* key;
every key in SDL_KEYUP do
_queue_put(_CEU_IN_SDL_KEYUP,
sizeof(_SDL_KeyboardEvent), (byte*)key
#ifdef TM_SNAP
, 0
#endif
)
finalize with
nothing;
end;
end
end
end
await this.go_off;
end
with
var _tceu_queue* qu;
every qu in this.go_queue do
var int evt = qu:evt;
var _SDL_KeyboardEvent val = *((_SDL_KeyboardEvent*)qu:buf);
if evt == _CEU_IN_SDL_KEYDOWN then
async(val) do
emit SDL_KEYDOWN => &val;
end
else/if evt == _CEU_IN_SDL_KEYUP then
async(val) do
emit SDL_KEYUP => &val;
end
else
_assert(0);
end
end
end
end
var IOTimeMachine io;
#endif // TM_QUEUE
var TimeMachine tm with
this.app = app;
#ifdef TM_QUEUE
this.io = io;
#endif
end;
var UITimeMachine uitm with
this.tm = tm;
end;
class G with
var TimeMachine& tm_;
event bool in_tm;
var bool blur;
do
end
var G g with
this.blur = false;
this.tm_ = tm;
end;
class TimeKeyController with
var int k_alt, k_left, k_right;
event void ok;
var G& g;
do
g.blur = true;
emit g.in_tm => true;
emit g.tm_.go_on;
par/or do
var _SDL_KeyboardEvent* key = await SDL_KEYUP_
until key:keysym.sym == this.k_alt;
with
loop do
var _SDL_KeyboardEvent* key = await SDL_KEYDOWN_;
var int sym2 = key:keysym.sym;
if sym2 == this.k_left then
if g.tm_.time_total-g.tm_.time_now < 2000 then
emit g.tm_.go_backward => 2;
end
else/if sym2 == this.k_right then
emit g.tm_.go_forward => 2;
end
par/or do
key = await SDL_KEYUP_ until key:keysym.sym == sym2;
with
var int time_now;
every time_now in g.tm_.ok_seek do
if g.tm_.time_total-time_now >= 2000 then
break;
end
end
end
emit g.tm_.go_pause;
end
end
emit g.tm_.go_off;
TM_AWAIT_SEEK(g.tm_);
emit g.in_tm => false;
g.blur = false;
emit this.ok;
end
par/or do
await SDL_QUIT_;
with
loop do
var _SDL_KeyboardEvent* key = await SDL_KEYDOWN_;
var int sym = key:keysym.sym;
if sym == _SDLK_ESCAPE then
emit g.in_tm => true;
emit tm.go_on;
emit uitm.go_on;
key = await SDL_KEYDOWN_ until key:keysym.sym == _SDLK_ESCAPE;
emit tm.go_off;
TM_AWAIT_SEEK(tm);
emit uitm.go_off;
emit g.in_tm => false;
else/if sym==_SDLK_LALT and _TIME1>0 then
_TIME1 = _TIME1 - 1;
do TimeKeyController with
this.k_alt = _SDLK_LALT;
this.k_left = _SDLK_a;
this.k_right = _SDLK_d;
this.g = g;
end;
else/if sym==_SDLK_RALT and _TIME2>0 then
_TIME2 = _TIME2 - 1;
do TimeKeyController with
this.k_alt = _SDLK_RALT;
this.k_left = _SDLK_LEFT;
this.k_right = _SDLK_RIGHT;
this.g = g;
end;
end
end
with
every SDL_REDRAW do
emit uitm.go_redraw;
if g.blur then
_boxRGBA(_REN, 0, 0, _REN_W, _REN_H, 0xAA,0x88,0x88,0x88);
end
_SDL_RenderPresent(_UITM_REN);
end
#if 0
with
loop do
var _SDL_KeyboardEvent* key = await SDL_KEYDOWN_
until key:keysym.sym == _SDLK_LCTRL;
var bool ok =
par do
key = await SDL_KEYUP_ until key:keysym.sym == _SDLK_LCTRL;
escape false;
with
await 1s;
escape true;
end;
if not ok then
continue;
end
_assert(_CEU_TIMEMACHINE_ON == 0);
_CEU_TIMEMACHINE_ON = 1;
finalize with
_CEU_TIMEMACHINE_ON = 0;
end
pause/if in_tm do
par/or do
loop do
key = await SDL_KEYDOWN_
until key:keysym.sym == _SDLK_LCTRL;
par/or do
key = await SDL_KEYUP_
until key:keysym.sym == _SDLK_LCTRL;
with
await 1s;
break;
end
end
with
#include "input.ceu"
end
end
end
#endif
with
var int fps = 0; // previous FPS
loop do
var int c = 0; // reset the current counter
watching 1s_ do
every SDL_DT_ do
c = c + 1;
end
end
fps = c;
//_printf("[FPS=%d]\n", fps);
end
end
escape 0;