]> git.lizzy.rs Git - nothing.git/blob - src/game.c
Make the color of the background layer mor subtle. Close #175
[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     camera_present(game->camera);
103
104     return 0;
105 }
106
107 int game_sound(game_t *game)
108 {
109     return level_sound(game->level, game->sound_samples);
110 }
111
112 int game_update(game_t *game, float delta_time)
113 {
114     assert(game);
115     assert(delta_time > 0.0f);
116
117     if (game->state == GAME_STATE_QUIT) {
118         return 0;
119     }
120
121     if (game->state == GAME_STATE_RUNNING) {
122         return level_update(game->level, delta_time);
123     }
124
125     return 0;
126 }
127
128
129 static int game_event_pause(game_t *game, const SDL_Event *event)
130 {
131     assert(game);
132     assert(event);
133
134     switch (event->type) {
135     case SDL_QUIT:
136         game->state = GAME_STATE_QUIT;
137         break;
138
139     case SDL_KEYDOWN:
140         switch (event->key.keysym.sym) {
141         case SDLK_p:
142             game->state = GAME_STATE_RUNNING;
143             camera_toggle_blackwhite_mode(game->camera);
144             sound_samples_toggle_pause(game->sound_samples);
145             break;
146         case SDLK_l:
147             camera_toggle_debug_mode(game->camera);
148             break;
149         }
150         break;
151     }
152
153     return level_event(game->level, event);
154 }
155
156 static int game_event_running(game_t *game, const SDL_Event *event)
157 {
158     assert(game);
159     assert(event);
160
161     switch (event->type) {
162     case SDL_QUIT:
163         game->state = GAME_STATE_QUIT;
164         break;
165
166     case SDL_KEYDOWN:
167         switch (event->key.keysym.sym) {
168         case SDLK_r:
169             printf("Reloading the level from '%s'...\n", game->level_file_path);
170
171             game->level = RESET_LT(
172                 game->lt,
173                 game->level,
174                 create_level_from_file(
175                     game->level_file_path));
176
177             if (game->level == NULL) {
178                 print_current_error_msg("Could not reload the level");
179                 game->state = GAME_STATE_QUIT;
180                 return -1;
181             }
182             break;
183
184         case SDLK_q:
185             printf("Reloading the level's platforms from '%s'...\n", game->level_file_path);
186             if (level_reload_preserve_player(game->level, game->level_file_path) < 0) {
187                 print_current_error_msg("Could not reload the level");
188                 game->state = GAME_STATE_QUIT;
189                 return -1;
190             }
191             break;
192
193         case SDLK_p:
194             game->state = GAME_STATE_PAUSE;
195             camera_toggle_blackwhite_mode(game->camera);
196             sound_samples_toggle_pause(game->sound_samples);
197             break;
198
199         case SDLK_l:
200             camera_toggle_debug_mode(game->camera);
201             break;
202         }
203         break;
204
205     }
206
207     return level_event(game->level, event);
208 }
209
210 int game_event(game_t *game, const SDL_Event *event)
211 {
212     assert(game);
213     assert(event);
214
215     switch (game->state) {
216     case GAME_STATE_RUNNING:
217         return game_event_running(game, event);
218
219     case GAME_STATE_PAUSE:
220         return game_event_pause(game, event);
221
222     default: {}
223     }
224
225     return 0;
226 }
227
228
229 int game_input(game_t *game,
230                const Uint8 *const keyboard_state,
231                SDL_Joystick *the_stick_of_joy)
232 {
233     assert(game);
234     assert(keyboard_state);
235
236     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
237         return 0;
238     }
239
240     return level_input(game->level, keyboard_state, the_stick_of_joy);
241 }
242
243 int game_over_check(const game_t *game)
244 {
245     return game->state == GAME_STATE_QUIT;
246 }