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