]> git.lizzy.rs Git - nothing.git/blob - src/game.c
2cf2b45316fed580e53c4d96a0b5cc9d80440f05
[nothing.git] / src / game.c
1 #include <stdio.h>
2 #include <assert.h>
3 #include <SDL2/SDL.h>
4 #include <SDL2/SDL_mixer.h>
5
6 #include "./player.h"
7 #include "./platforms.h"
8 #include "./game.h"
9 #include "./error.h"
10 #include "./level.h"
11 #include "./sound_medium.h"
12 #include "./lt.h"
13
14 typedef enum game_state_t {
15     GAME_STATE_RUNNING = 0,
16     GAME_STATE_PAUSE,
17     GAME_STATE_QUIT,
18
19     GAME_STATE_N
20 } game_state_t;
21
22 typedef struct game_t {
23     lt_t *lt;
24
25     game_state_t state;
26     level_t *level;
27     char *level_file_path;
28 } game_t;
29
30 game_t *create_game(const char *level_file_path)
31 {
32     assert(level_file_path);
33
34     lt_t *const lt = create_lt();
35     if (lt == NULL) {
36         return NULL;
37     }
38
39     game_t *game = PUSH_LT(lt, malloc(sizeof(game_t)), free);
40     if (game == NULL) {
41         throw_error(ERROR_TYPE_LIBC);
42         RETURN_LT(lt, NULL);
43     }
44
45     game->level = PUSH_LT(
46         lt,
47         create_level_from_file(level_file_path),
48         destroy_level);
49     if (game->level == NULL) {
50         RETURN_LT(lt, NULL);
51     }
52
53     game->level_file_path = PUSH_LT(lt, malloc(sizeof(char) * (strlen(level_file_path) + 1)), free);
54     if (game->level_file_path == NULL) {
55         throw_error(ERROR_TYPE_LIBC);
56         RETURN_LT(lt, NULL);
57     }
58
59     strcpy(game->level_file_path, level_file_path);
60
61     game->state = GAME_STATE_RUNNING;
62     game->lt = lt;
63
64     return game;
65 }
66
67 void destroy_game(game_t *game)
68 {
69     assert(game);
70     RETURN_LT0(game->lt);
71 }
72
73 int game_render(const game_t *game, SDL_Renderer *renderer)
74 {
75     assert(game);
76     assert(renderer);
77
78     if (game->state == GAME_STATE_QUIT) {
79         return 0;
80     }
81
82     if (level_render(game->level, renderer) < 0) {
83         return -1;
84     }
85
86     SDL_RenderPresent(renderer);
87
88     return 0;
89 }
90
91 int game_update(game_t *game, Uint32 delta_time)
92 {
93     assert(game);
94     assert(delta_time > 0);
95
96     if (game->state == GAME_STATE_QUIT) {
97         return 0;
98     }
99
100     if (game->state == GAME_STATE_RUNNING) {
101         return level_update(game->level, delta_time);
102     }
103
104     return 0;
105 }
106
107
108 static int game_event_pause(game_t *game, const SDL_Event *event)
109 {
110     assert(game);
111     assert(event);
112
113     switch (event->type) {
114     case SDL_QUIT:
115         game->state = GAME_STATE_QUIT;
116         break;
117
118     case SDL_KEYDOWN:
119         switch (event->key.keysym.sym) {
120         case SDLK_p:
121             game->state = GAME_STATE_RUNNING;
122             level_toggle_pause_mode(game->level);
123             break;
124         case SDLK_l:
125             level_toggle_debug_mode(game->level);
126             break;
127         }
128         break;
129     }
130
131     return level_event(game->level, event);
132 }
133
134 static int game_event_running(game_t *game, const SDL_Event *event)
135 {
136     assert(game);
137     assert(event);
138
139     switch (event->type) {
140     case SDL_QUIT:
141         game->state = GAME_STATE_QUIT;
142         break;
143
144     case SDL_KEYDOWN:
145         switch (event->key.keysym.sym) {
146         case SDLK_r:
147             printf("Reloading the level from '%s'...\n", game->level_file_path);
148
149             game->level = RESET_LT(
150                 game->lt,
151                 game->level,
152                 create_level_from_file(
153                     game->level_file_path));
154
155             if (game->level == NULL) {
156                 print_current_error_msg("Could not reload the level");
157                 game->state = GAME_STATE_QUIT;
158                 return -1;
159             }
160             break;
161
162         case SDLK_q:
163             printf("Reloading the level's platforms from '%s'...\n", game->level_file_path);
164             if (level_reload_preserve_player(game->level, game->level_file_path) < 0) {
165                 print_current_error_msg("Could not reload the level");
166                 game->state = GAME_STATE_QUIT;
167                 return -1;
168             }
169             break;
170
171         case SDLK_p:
172             game->state = GAME_STATE_PAUSE;
173             level_toggle_pause_mode(game->level);
174             break;
175
176         case SDLK_l:
177             level_toggle_debug_mode(game->level);
178             break;
179         }
180         break;
181
182     }
183
184     return level_event(game->level, event);
185 }
186
187 int game_event(game_t *game, const SDL_Event *event)
188 {
189     assert(game);
190     assert(event);
191
192     switch (game->state) {
193     case GAME_STATE_RUNNING:
194         return game_event_running(game, event);
195
196     case GAME_STATE_PAUSE:
197         return game_event_pause(game, event);
198
199     default: {}
200     }
201
202     return 0;
203 }
204
205
206 int game_input(game_t *game,
207                const Uint8 *const keyboard_state,
208                SDL_Joystick *the_stick_of_joy)
209 {
210     assert(game);
211     assert(keyboard_state);
212
213     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
214         return 0;
215     }
216
217     return level_input(game->level, keyboard_state, the_stick_of_joy);
218 }
219
220 int game_over_check(const game_t *game)
221 {
222     return game->state == GAME_STATE_QUIT;
223 }