comparison libmlk-core/mlk/core/game.c @ 431:8f59201dc76b

core: cleanup hierarchy
author David Demelier <markand@malikania.fr>
date Sat, 15 Oct 2022 20:23:14 +0200
parents src/libmlk-core/core/game.c@3edda1ce314c
children 773a082f0b91
comparison
equal deleted inserted replaced
430:1645433e008d 431:8f59201dc76b
1 /*
2 * game.c -- main game object
3 *
4 * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20 #include <string.h>
21
22 #include "clock.h"
23 #include "event.h"
24 #include "game.h"
25 #include "state.h"
26 #include "util.h"
27 #include "window.h"
28
29 struct game game = {0};
30
31 void
32 game_init(struct state **states, size_t statesz)
33 {
34 assert(states);
35 assert(statesz);
36
37 memset(&game, 0, sizeof (game));
38
39 game.states = states;
40 game.statesz = statesz;
41
42 for (size_t i = 0; i < game.statesz; ++i)
43 game.states[i] = NULL;
44 }
45
46 void
47 game_push(struct state *state)
48 {
49 assert(state);
50 assert(!game.state || game.state != &game.states[game.statesz - 1]);
51
52 if (!game.state) {
53 game.state = &game.states[0];
54 state_start(*game.state = state);
55 } else {
56 state_suspend(*game.state);
57 state_start(*(++game.state) = state);
58 }
59 }
60
61 void
62 game_pop(void)
63 {
64 assert(game.state);
65
66 state_end(*game.state);
67 state_finish(*game.state);
68
69 if (game.state == game.states)
70 game.state = NULL;
71 else
72 state_resume(*--game.state);
73 }
74
75 void
76 game_handle(const union event *ev)
77 {
78 assert(ev);
79
80 if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
81 state_handle(*game.state, ev);
82 }
83
84 void
85 game_update(unsigned int ticks)
86 {
87 if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE))
88 state_update(*game.state, ticks);
89 }
90
91 void
92 game_draw(void)
93 {
94 if (*game.state && !(game.inhibit & INHIBIT_STATE_DRAW))
95 state_draw(*game.state);
96 }
97
98 void
99 game_loop(void)
100 {
101 struct mlk_clock clock = {0};
102 unsigned int elapsed = 0;
103 unsigned int frametime;
104
105 if (window.framerate > 0)
106 frametime = 1000 / window.framerate;
107 else
108 /* Assuming 50.0 FPS. */
109 frametime = 1000.0 / 50.0;
110
111 while (*game.state) {
112 mlk_clock_start(&clock);
113
114 for (union event ev; event_poll(&ev); )
115 game_handle(&ev);
116
117 game_update(elapsed);
118 game_draw();
119
120 /*
121 * If vsync is enabled, it should have wait, otherwise sleep
122 * a little to save CPU cycles.
123 */
124 if ((elapsed = mlk_clock_elapsed(&clock)) < frametime)
125 util_delay(frametime - elapsed);
126
127 elapsed = mlk_clock_elapsed(&clock);
128 }
129 }
130
131 void
132 game_quit(void)
133 {
134 for (size_t i = 0; i < game.statesz; ++i) {
135 if (game.states[i])
136 state_finish(game.states[i]);
137
138 game.states[i] = NULL;
139 }
140 }