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