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