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