]> git.lizzy.rs Git - nothing.git/blob - src/game.c
Integrate game entity with lt module
[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         }
146         break;
147     }
148
149     return 0;
150 }
151
152 static int game_event_running(game_t *game, const SDL_Event *event)
153 {
154     assert(game);
155     assert(event);
156
157     switch (event->type) {
158     case SDL_QUIT:
159         game->state = GAME_STATE_QUIT;
160         break;
161
162     case SDL_KEYDOWN:
163         switch (event->key.keysym.sym) {
164         case SDLK_SPACE:
165             player_jump(game->player);
166             break;
167
168         case SDLK_q:
169             printf("Reloading the level from '%s'...", game->level_file_path);
170
171             game->platforms = RESET_LT(
172                 game->lt,
173                 game->platforms,
174                 load_platforms_from_file(game->level_file_path));
175
176             if (game->platforms == NULL) {
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             break;
186         }
187         break;
188
189     case SDL_JOYBUTTONDOWN:
190         if (event->jbutton.button == 1) {
191             player_jump(game->player);
192         }
193         break;
194     }
195
196     return 0;
197 }
198
199 int game_event(game_t *game, const SDL_Event *event)
200 {
201     assert(game);
202     assert(event);
203
204     switch (game->state) {
205     case GAME_STATE_RUNNING:
206         return game_event_running(game, event);
207
208     case GAME_STATE_PAUSE:
209         return game_event_pause(game, event);
210
211     default: {}
212     }
213
214     return 0;
215 }
216
217
218 int game_input(game_t *game,
219                const Uint8 *const keyboard_state,
220                SDL_Joystick *the_stick_of_joy)
221 {
222     assert(game);
223     assert(keyboard_state);
224     assert(the_stick_of_joy);
225
226     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
227         return 0;
228     }
229
230     if (keyboard_state[SDL_SCANCODE_A]) {
231         player_move_left(game->player);
232     } else if (keyboard_state[SDL_SCANCODE_D]) {
233         player_move_right(game->player);
234     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) < 0) {
235         player_move_left(game->player);
236     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) > 0) {
237         player_move_right(game->player);
238     } else {
239         player_stop(game->player);
240     }
241
242     return 0;
243 }
244
245 int is_game_over(const game_t *game)
246 {
247     return game->state == GAME_STATE_QUIT;
248 }