annotate libmlk-core/mlk/core/game.c @ 634:3930234ab1f5

examples: add basic gamepad
author David Demelier <markand@malikania.fr>
date Tue, 29 Aug 2023 13:34:10 +0200
parents 4349b591c3ac
children 83781cc87fca
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 *
445
773a082f0b91 misc: update copyright years
David Demelier <markand@malikania.fr>
parents: 431
diff changeset
4 * Copyright (c) 2020-2023 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"
586
4349b591c3ac cmake: put NLS back
David Demelier <markand@malikania.fr>
parents: 585
diff changeset
23 #include "core_p.h"
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
24 #include "err.h"
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
25 #include "event.h"
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #include "game.h"
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 #include "state.h"
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
28 #include "util.h"
248
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
29 #include "window.h"
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
30
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
31 static struct mlk_state *states[8];
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
32
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
33 struct mlk_game mlk_game = {
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
34 .states = states,
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
35 .statesz = MLK_UTIL_SIZE(states)
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
36 };
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
37
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 void
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
39 mlk_game_init(void)
311
f10fd1293a7e core: fix states + tests
David Demelier <markand@malikania.fr>
parents: 300
diff changeset
40 {
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
41 for (size_t i = 0; i < mlk_game.statesz; ++i)
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
42 mlk_game.states[i] = NULL;
311
f10fd1293a7e core: fix states + tests
David Demelier <markand@malikania.fr>
parents: 300
diff changeset
43 }
f10fd1293a7e core: fix states + tests
David Demelier <markand@malikania.fr>
parents: 300
diff changeset
44
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
45 int
469
0d6206cee6b9 core: state -> mlk_state
David Demelier <markand@malikania.fr>
parents: 454
diff changeset
46 mlk_game_push(struct mlk_state *state)
45
e10fd1b6323f core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents: 44
diff changeset
47 {
e10fd1b6323f core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents: 44
diff changeset
48 assert(state);
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
49
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
50 if (!mlk_game.state) {
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
51 mlk_game.state = &mlk_game.states[0];
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
52 mlk_state_start(*mlk_game.state = state);
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
53 return 0;
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
54 }
162
629f55f3961e core: rework states
David Demelier <markand@malikania.fr>
parents: 147
diff changeset
55
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
56 if (mlk_game.state == &mlk_game.states[mlk_game.statesz - 1])
586
4349b591c3ac cmake: put NLS back
David Demelier <markand@malikania.fr>
parents: 585
diff changeset
57 return mlk_errf(_("no space in game states stack"));
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
58
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
59 mlk_state_suspend(*mlk_game.state);
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
60 mlk_state_start(*(++mlk_game.state) = state);
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
61
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
62 return 0;
45
e10fd1b6323f core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents: 44
diff changeset
63 }
e10fd1b6323f core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents: 44
diff changeset
64
299
648f5f949afb core: implement stackable states
David Demelier <markand@malikania.fr>
parents: 298
diff changeset
65 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
66 mlk_game_pop(void)
260
60a214ec1ab4 adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents: 248
diff changeset
67 {
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
68 if (!mlk_game.state)
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
69 return;
260
60a214ec1ab4 adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents: 248
diff changeset
70
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
71 mlk_state_end(*mlk_game.state);
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
72 mlk_state_finish(*mlk_game.state);
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
73
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
74 if (mlk_game.state == mlk_game.states)
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
75 mlk_game.state = NULL;
389
ef4d4a51aeb7 core: game don't use fixed size states
David Demelier <markand@malikania.fr>
parents: 378
diff changeset
76 else
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
77 mlk_state_resume(*--mlk_game.state);
260
60a214ec1ab4 adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents: 248
diff changeset
78 }
60a214ec1ab4 adventure: change the way states are stored
David Demelier <markand@malikania.fr>
parents: 248
diff changeset
79
45
e10fd1b6323f core: implement splashscreen, closes #2458 @1h
David Demelier <markand@malikania.fr>
parents: 44
diff changeset
80 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
81 mlk_game_handle(const union mlk_event *ev)
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 {
162
629f55f3961e core: rework states
David Demelier <markand@malikania.fr>
parents: 147
diff changeset
83 assert(ev);
57
9f6267843815 core: implement basic actions, closes #2463 @1h
David Demelier <markand@malikania.fr>
parents: 45
diff changeset
84
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
85 if (mlk_game.state && !(mlk_game.inhibit & MLK_GAME_INHIBIT_INPUT))
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
86 mlk_state_handle(*mlk_game.state, ev);
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 }
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
88
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
90 mlk_game_update(unsigned int ticks)
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 {
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
92 if (mlk_game.state && !(mlk_game.inhibit & MLK_GAME_INHIBIT_UPDATE))
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
93 mlk_state_update(*mlk_game.state, ticks);
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 }
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
95
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
97 mlk_game_draw(void)
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 {
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
99 if (mlk_game.state && !(mlk_game.inhibit & MLK_GAME_INHIBIT_DRAW))
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
100 mlk_state_draw(*mlk_game.state);
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
101 }
58
d7d88ac30611 core: forgot to implement action->draw
David Demelier <markand@malikania.fr>
parents: 57
diff changeset
102
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
103 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
104 mlk_game_loop(void)
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
105 {
421
3edda1ce314c core: remove mlk_ prefix for now
David Demelier <markand@malikania.fr>
parents: 400
diff changeset
106 struct mlk_clock clock = {0};
248
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
107 unsigned int elapsed = 0;
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
108 unsigned int frametime;
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
109
485
3ff1fe64d0cd core: window -> mlk_window
David Demelier <markand@malikania.fr>
parents: 474
diff changeset
110 if (mlk_window.framerate > 0)
3ff1fe64d0cd core: window -> mlk_window
David Demelier <markand@malikania.fr>
parents: 474
diff changeset
111 frametime = 1000 / mlk_window.framerate;
248
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
112 else
583
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
113 /* Assuming 60.0 FPS. */
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
114 frametime = 1000.0 / 60.0;
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
115
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
116 while (mlk_game.state) {
421
3edda1ce314c core: remove mlk_ prefix for now
David Demelier <markand@malikania.fr>
parents: 400
diff changeset
117 mlk_clock_start(&clock);
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
118
450
b26dd49f69ff core: event -> mlk_event (and friends)
David Demelier <markand@malikania.fr>
parents: 445
diff changeset
119 for (union mlk_event ev; mlk_event_poll(&ev); )
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
120 mlk_game_handle(&ev);
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
121
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
122 mlk_game_update(elapsed);
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
123 mlk_game_draw();
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
124
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
125 /*
248
37771eaf4245 core: use vsync and improve game loop
David Demelier <markand@malikania.fr>
parents: 243
diff changeset
126 * 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
127 * a little to save CPU cycles.
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
128 */
421
3edda1ce314c core: remove mlk_ prefix for now
David Demelier <markand@malikania.fr>
parents: 400
diff changeset
129 if ((elapsed = mlk_clock_elapsed(&clock)) < frametime)
585
76ce31b0151f misc: minor edits
David Demelier <markand@malikania.fr>
parents: 583
diff changeset
130 mlk_util_sleep(frametime - elapsed);
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
131
421
3edda1ce314c core: remove mlk_ prefix for now
David Demelier <markand@malikania.fr>
parents: 400
diff changeset
132 elapsed = mlk_clock_elapsed(&clock);
583
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
133
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
134 /*
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
135 * Cap to frametime if it's too slow because it would create
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
136 * unexpected results otherwise.
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
137 */
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
138 if (elapsed > frametime)
5a4e5b852f8a core: make sure we never exceed 60FPS ticks
David Demelier <markand@malikania.fr>
parents: 547
diff changeset
139 elapsed = frametime;
207
133926e08d6e examples: use game_loop for all
David Demelier <markand@malikania.fr>
parents: 165
diff changeset
140 }
44
c97fe725fdeb core: implement basic states, closes #2457 @1h
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 }
57
9f6267843815 core: implement basic actions, closes #2463 @1h
David Demelier <markand@malikania.fr>
parents: 45
diff changeset
142
80
05ffbcdee585 adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents: 78
diff changeset
143 void
452
f89147faf8cf core: game -> mlk_game
David Demelier <markand@malikania.fr>
parents: 450
diff changeset
144 mlk_game_quit(void)
80
05ffbcdee585 adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents: 78
diff changeset
145 {
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
146 for (size_t i = 0; i < mlk_game.statesz; ++i) {
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
147 if (mlk_game.states[i])
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
148 mlk_state_finish(mlk_game.states[i]);
300
3638b39ef2bf examples: fix with new game_push function
David Demelier <markand@malikania.fr>
parents: 299
diff changeset
149
522
f45a023f6690 core: doxygenize game
David Demelier <markand@malikania.fr>
parents: 485
diff changeset
150 mlk_game.states[i] = NULL;
311
f10fd1293a7e core: fix states + tests
David Demelier <markand@malikania.fr>
parents: 300
diff changeset
151 }
529
7e835d43ef74 core: fix game crash
David Demelier <markand@malikania.fr>
parents: 522
diff changeset
152
7e835d43ef74 core: fix game crash
David Demelier <markand@malikania.fr>
parents: 522
diff changeset
153 mlk_game.state = NULL;
80
05ffbcdee585 adventure: create main menu, closes #2482 @4h
David Demelier <markand@malikania.fr>
parents: 78
diff changeset
154 }