]> git.lizzy.rs Git - nothing.git/blob - src/game.c
c59083d93c58d891ab4849cda737371ca35ec14f
[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 (level_render(game->level, renderer) < 0) {
81         return -1;
82     }
83
84     SDL_RenderPresent(renderer);
85
86     return 0;
87 }
88
89 int game_update(game_t *game, Uint32 delta_time)
90 {
91     assert(game);
92     assert(delta_time > 0);
93
94     if (game->state == GAME_STATE_QUIT) {
95         return 0;
96     }
97
98     if (game->state == GAME_STATE_RUNNING) {
99         return level_update(game->level, delta_time);
100     }
101
102     return 0;
103 }
104
105
106 static int game_event_pause(game_t *game, const SDL_Event *event)
107 {
108     assert(game);
109     assert(event);
110
111     switch (event->type) {
112     case SDL_QUIT:
113         game->state = GAME_STATE_QUIT;
114         break;
115
116     case SDL_KEYDOWN:
117         switch (event->key.keysym.sym) {
118         case SDLK_p:
119             game->state = GAME_STATE_RUNNING;
120             level_toggle_pause_mode(game->level);
121             break;
122         case SDLK_l:
123             level_toggle_debug_mode(game->level);
124             break;
125         }
126         break;
127     }
128
129     return level_event(game->level, event);
130 }
131
132 static int game_event_running(game_t *game, const SDL_Event *event)
133 {
134     assert(game);
135     assert(event);
136
137     switch (event->type) {
138     case SDL_QUIT:
139         game->state = GAME_STATE_QUIT;
140         break;
141
142     case SDL_KEYDOWN:
143         switch (event->key.keysym.sym) {
144         case SDLK_r:
145             printf("Reloading the level from '%s'...\n", game->level_file_path);
146
147             game->level = RESET_LT(
148                 game->lt,
149                 game->level,
150                 create_level_from_file(game->level_file_path));
151
152             if (game->level == NULL) {
153                 print_current_error_msg("Could not reload the level");
154                 game->state = GAME_STATE_QUIT;
155                 return -1;
156             }
157             break;
158
159         case SDLK_q:
160             printf("Reloading the level's platforms from '%s'...\n", game->level_file_path);
161             if (level_reload_preserve_player(game->level, game->level_file_path) < 0) {
162                 print_current_error_msg("Could not reload the level");
163                 game->state = GAME_STATE_QUIT;
164                 return -1;
165             }
166             break;
167
168         case SDLK_p:
169             game->state = GAME_STATE_PAUSE;
170             level_toggle_pause_mode(game->level);
171             break;
172
173         case SDLK_l:
174             level_toggle_debug_mode(game->level);
175             break;
176         }
177         break;
178
179     }
180
181     return level_event(game->level, event);
182 }
183
184 int game_event(game_t *game, const SDL_Event *event)
185 {
186     assert(game);
187     assert(event);
188
189     switch (game->state) {
190     case GAME_STATE_RUNNING:
191         return game_event_running(game, event);
192
193     case GAME_STATE_PAUSE:
194         return game_event_pause(game, event);
195
196     default: {}
197     }
198
199     return 0;
200 }
201
202
203 int game_input(game_t *game,
204                const Uint8 *const keyboard_state,
205                SDL_Joystick *the_stick_of_joy)
206 {
207     assert(game);
208     assert(keyboard_state);
209
210     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
211         return 0;
212     }
213
214     return level_input(game->level, keyboard_state, the_stick_of_joy);
215 }
216
217 int game_over_check(const game_t *game)
218 {
219     return game->state == GAME_STATE_QUIT;
220 }