]> git.lizzy.rs Git - nothing.git/blob - src/game.c
8f2df1d9b63256825618423cb5f5dc99de87b0dd
[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 "./camera.h"
8 #include "./game.h"
9 #include "./error.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     player_t *player;
25     platforms_t *platforms;
26     camera_t *camera;
27     char *level_file_path;
28 } game_t;
29
30 game_t *create_game(const char *level_file_path)
31 {
32     assert(level_file_path);
33
34     lt_t *const lt = create_lt();
35     if (lt == NULL) {
36         return NULL;
37     }
38
39     game_t *game = PUSH_LT(lt, malloc(sizeof(game_t)), free);
40     if (game == NULL) {
41         throw_error(ERROR_TYPE_LIBC);
42         RETURN_LT(lt, NULL);
43     }
44
45     game->player = PUSH_LT(lt, create_player(100.0f, 0.0f), destroy_player);
46     if (game->player == NULL) {
47         RETURN_LT(lt, NULL);
48     }
49
50     game->platforms = PUSH_LT(lt, load_platforms_from_file(level_file_path), destroy_platforms);
51     if (game->platforms == NULL) {
52         RETURN_LT(lt, NULL);
53     }
54
55     game->camera = PUSH_LT(lt, create_camera(vec(0.0f, 0.0f)), destroy_camera);
56     if (game->camera == NULL) {
57         RETURN_LT(lt, NULL);
58     }
59
60     game->level_file_path = PUSH_LT(lt, malloc(sizeof(char) * (strlen(level_file_path) + 1)), free);
61     if (game->level_file_path == NULL) {
62         throw_error(ERROR_TYPE_LIBC);
63         RETURN_LT(lt, NULL);
64     }
65
66     strcpy(game->level_file_path, level_file_path);
67
68     game->state = GAME_STATE_RUNNING;
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, SDL_Renderer *renderer)
81 {
82     assert(game);
83     assert(renderer);
84
85     if (game->state == GAME_STATE_QUIT) {
86         return 0;
87     }
88
89     if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) < 0) {
90         throw_error(ERROR_TYPE_SDL2);
91         return -1;
92     }
93
94     if (SDL_RenderClear(renderer) < 0) {
95         throw_error(ERROR_TYPE_SDL2);
96         return -1;
97     }
98
99     if (render_player(game->player, renderer, game->camera) < 0) {
100         return -1;
101     }
102
103     if (render_platforms(game->platforms, renderer, game->camera) < 0) {
104         return -1;
105     }
106
107     SDL_RenderPresent(renderer);
108
109     return 0;
110 }
111
112 int game_update(game_t *game, Uint32 delta_time)
113 {
114     assert(game);
115     assert(delta_time > 0);
116
117     if (game->state == GAME_STATE_QUIT) {
118         return 0;
119     }
120
121     if (game->state == GAME_STATE_RUNNING) {
122         update_player(game->player, game->platforms, delta_time);
123         player_focus_camera(game->player, game->camera);
124     }
125
126     return 0;
127 }
128
129
130 static int game_event_pause(game_t *game, const SDL_Event *event)
131 {
132     assert(game);
133     assert(event);
134
135     switch (event->type) {
136     case SDL_QUIT:
137         game->state = GAME_STATE_QUIT;
138         break;
139
140     case SDL_KEYDOWN:
141         switch (event->key.keysym.sym) {
142         case SDLK_p:
143             game->state = GAME_STATE_RUNNING;
144             break;
145         case SDLK_l:
146             camera_toggle_debug_mode(game->camera);
147             break;
148         }
149         break;
150     }
151
152     return 0;
153 }
154
155 static int game_event_running(game_t *game, const SDL_Event *event)
156 {
157     assert(game);
158     assert(event);
159
160     switch (event->type) {
161     case SDL_QUIT:
162         game->state = GAME_STATE_QUIT;
163         break;
164
165     case SDL_KEYDOWN:
166         switch (event->key.keysym.sym) {
167         case SDLK_SPACE:
168             player_jump(game->player);
169             break;
170
171         case SDLK_q:
172             printf("Reloading the level from '%s'...\n", game->level_file_path);
173
174             game->platforms = RESET_LT(
175                 game->lt,
176                 game->platforms,
177                 load_platforms_from_file(game->level_file_path));
178
179             if (game->platforms == NULL) {
180                 print_current_error_msg("Could not reload the level");
181                 game->state = GAME_STATE_QUIT;
182                 return -1;
183             }
184             break;
185
186         case SDLK_p:
187             game->state = GAME_STATE_PAUSE;
188             break;
189
190         case SDLK_l:
191             camera_toggle_debug_mode(game->camera);
192             break;
193         }
194         break;
195
196     case SDL_JOYBUTTONDOWN:
197         if (event->jbutton.button == 1) {
198             player_jump(game->player);
199         }
200         break;
201     }
202
203     return 0;
204 }
205
206 int game_event(game_t *game, const SDL_Event *event)
207 {
208     assert(game);
209     assert(event);
210
211     switch (game->state) {
212     case GAME_STATE_RUNNING:
213         return game_event_running(game, event);
214
215     case GAME_STATE_PAUSE:
216         return game_event_pause(game, event);
217
218     default: {}
219     }
220
221     return 0;
222 }
223
224
225 int game_input(game_t *game,
226                const Uint8 *const keyboard_state,
227                SDL_Joystick *the_stick_of_joy)
228 {
229     assert(game);
230     assert(keyboard_state);
231
232     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
233         return 0;
234     }
235
236     if (keyboard_state[SDL_SCANCODE_A]) {
237         player_move_left(game->player);
238     } else if (keyboard_state[SDL_SCANCODE_D]) {
239         player_move_right(game->player);
240     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) < 0) {
241         player_move_left(game->player);
242     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) > 0) {
243         player_move_right(game->player);
244     } else {
245         player_stop(game->player);
246     }
247
248     return 0;
249 }
250
251 int is_game_over(const game_t *game)
252 {
253     return game->state == GAME_STATE_QUIT;
254 }