Mercurial > molko
annotate src/libmlk-core/core/game.c @ 419:1b4e61bdb9ab
core: introduce err.h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 12 Oct 2022 15:06:18 +0200 |
parents | 4fb0ce06a43a |
children | 3edda1ce314c |
rev | line source |
---|---|
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
1 /* |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
2 * game.c -- main game object |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
3 * |
378
460c78706989
misc: update copyright years
David Demelier <markand@malikania.fr>
parents:
320
diff
changeset
|
4 * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr> |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
5 * |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
7 * purpose with or without fee is hereby granted, provided that the above |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
8 * copyright notice and this permission notice appear in all copies. |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
9 * |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
17 */ |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
18 |
45
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
19 #include <assert.h> |
57
9f6267843815
core: implement basic actions, closes #2463 @1h
David Demelier <markand@malikania.fr>
parents:
45
diff
changeset
|
20 #include <string.h> |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
21 |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
22 #include "clock.h" |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
23 #include "event.h" |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
24 #include "game.h" |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
25 #include "state.h" |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
26 #include "util.h" |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
27 #include "window.h" |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
28 |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
29 struct game game = {0}; |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
30 |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
31 void |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
32 game_init(struct state **states, size_t statesz) |
311
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
33 { |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
34 assert(states); |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
35 assert(statesz); |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
36 |
311
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
37 memset(&game, 0, sizeof (game)); |
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
38 |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
39 game.states = states; |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
40 game.statesz = statesz; |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
41 |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
42 for (size_t i = 0; i < game.statesz; ++i) |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
43 game.states[i] = NULL; |
311
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
44 } |
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
45 |
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
46 void |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
47 game_push(struct state *state) |
45
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
48 { |
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
49 assert(state); |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
50 assert(!game.state || game.state != &game.states[game.statesz - 1]); |
162 | 51 |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
52 if (!game.state) { |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
53 game.state = &game.states[0]; |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
54 state_start(*game.state = state); |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
55 } else { |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
56 state_suspend(*game.state); |
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
57 state_start(*(++game.state) = state); |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
58 } |
45
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
59 } |
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
60 |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
61 void |
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
62 game_pop(void) |
260
60a214ec1ab4
adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents:
248
diff
changeset
|
63 { |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
64 assert(game.state); |
260
60a214ec1ab4
adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents:
248
diff
changeset
|
65 |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
66 state_end(*game.state); |
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
67 state_finish(*game.state); |
260
60a214ec1ab4
adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents:
248
diff
changeset
|
68 |
389
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
69 if (game.state == game.states) |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
70 game.state = NULL; |
ef4d4a51aeb7
core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents:
378
diff
changeset
|
71 else |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
72 state_resume(*--game.state); |
260
60a214ec1ab4
adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents:
248
diff
changeset
|
73 } |
60a214ec1ab4
adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents:
248
diff
changeset
|
74 |
45
e10fd1b6323f
core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents:
44
diff
changeset
|
75 void |
162 | 76 game_handle(const union event *ev) |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
77 { |
162 | 78 assert(ev); |
57
9f6267843815
core: implement basic actions, closes #2463 @1h
David Demelier <markand@malikania.fr>
parents:
45
diff
changeset
|
79 |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
80 if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT)) |
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
81 state_handle(*game.state, ev); |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
82 } |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
83 |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
84 void |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
85 game_update(unsigned int ticks) |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
86 { |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
87 if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE)) |
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
88 state_update(*game.state, ticks); |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
89 } |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
90 |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
91 void |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
92 game_draw(void) |
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
93 { |
300
3638b39ef2bf
examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents:
299
diff
changeset
|
94 if (*game.state && !(game.inhibit & INHIBIT_STATE_DRAW)) |
299
648f5f949afb
core: implement stackable states
David Demelier <markand@malikania.fr>
parents:
298
diff
changeset
|
95 state_draw(*game.state); |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
96 } |
58
d7d88ac30611
core: forgot to implement action->draw
David Demelier <markand@malikania.fr>
parents:
57
diff
changeset
|
97 |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
98 void |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
99 game_loop(void) |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
100 { |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
101 struct clock clock = {0}; |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
102 unsigned int elapsed = 0; |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
103 unsigned int frametime; |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
104 |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
105 if (window.framerate > 0) |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
106 frametime = 1000 / window.framerate; |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
107 else |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
108 /* Assuming 50.0 FPS. */ |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
109 frametime = 1000.0 / 50.0; |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
110 |
300
3638b39ef2bf
examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents:
299
diff
changeset
|
111 while (*game.state) { |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
112 clock_start(&clock); |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
113 |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
114 for (union event ev; event_poll(&ev); ) |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
115 game_handle(&ev); |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
116 |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
117 game_update(elapsed); |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
118 game_draw(); |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
119 |
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
120 /* |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
121 * If vsync is enabled, it should have wait, otherwise sleep |
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
122 * a little to save CPU cycles. |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
123 */ |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
124 if ((elapsed = clock_elapsed(&clock)) < frametime) |
261
bfde372bf152
core: prefix utilities with util_
David Demelier <markand@malikania.fr>
parents:
260
diff
changeset
|
125 util_delay(frametime - elapsed); |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
126 |
248
37771eaf4245
core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents:
243
diff
changeset
|
127 elapsed = clock_elapsed(&clock); |
207
133926e08d6e
examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents:
165
diff
changeset
|
128 } |
44
c97fe725fdeb
core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
129 } |
57
9f6267843815
core: implement basic actions, closes #2463 @1h
David Demelier <markand@malikania.fr>
parents:
45
diff
changeset
|
130 |
80
05ffbcdee585
adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
131 void |
05ffbcdee585
adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
132 game_quit(void) |
05ffbcdee585
adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
133 { |
400
4fb0ce06a43a
core: fix invalid use of game.states
David Demelier <markand@malikania.fr>
parents:
389
diff
changeset
|
134 for (size_t i = 0; i < game.statesz; ++i) { |
300
3638b39ef2bf
examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents:
299
diff
changeset
|
135 if (game.states[i]) |
3638b39ef2bf
examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents:
299
diff
changeset
|
136 state_finish(game.states[i]); |
3638b39ef2bf
examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents:
299
diff
changeset
|
137 |
311
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
138 game.states[i] = NULL; |
f10fd1293a7e
core: fix states + tests
David Demelier <markand@malikania.fr>
parents:
300
diff
changeset
|
139 } |
80
05ffbcdee585
adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
140 } |