]> git.lizzy.rs Git - nothing.git/blob - src/game.c
e0f3cf43de4cbb2bc0f665b6f393f827249e3d5a
[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
11 typedef enum game_state_t {
12     GAME_STATE_RUNNING = 0,
13     GAME_STATE_PAUSE,
14     GAME_STATE_QUIT,
15
16     GAME_STATE_N
17 } game_state_t;
18
19 typedef struct game_t {
20     game_state_t state;
21     player_t *player;
22     platforms_t *platforms;
23     camera_t *camera;
24     char *level_file_path;
25 } game_t;
26
27 game_t *create_game(const char *level_file_path)
28 {
29     assert(level_file_path);
30
31     game_t *game = malloc(sizeof(game_t));
32     if (game == NULL) {
33         throw_error(ERROR_TYPE_LIBC);
34         goto malloc_game_failed;
35     }
36
37     if ((game->player = create_player(100.0f, 0.0f)) == NULL) {
38         goto create_player_failed;
39     }
40
41     if ((game->platforms = load_platforms_from_file(level_file_path)) == NULL) {
42         goto create_platforms_failed;
43     }
44
45     if ((game->camera = create_camera(vec(0.0f, 0.0f))) == NULL) {
46         goto create_camera_failed;
47     }
48
49     if ((game->level_file_path = malloc(sizeof(char) * strlen(level_file_path))) == NULL) {
50         goto malloc_level_file_name_failed;
51     }
52
53     strcpy(game->level_file_path, level_file_path);
54
55     game->state = GAME_STATE_RUNNING;
56
57     return game;
58
59 malloc_level_file_name_failed:
60     free(game->camera);
61 create_camera_failed:
62     free(game->platforms);
63 create_platforms_failed:
64     free(game->player);
65 create_player_failed:
66     free(game);
67 malloc_game_failed:
68     return NULL;
69 }
70
71 void destroy_game(game_t *game)
72 {
73     assert(game);
74
75     if (game->level_file_path) { free(game->level_file_path); }
76     if (game->camera) { free(game->camera); }
77     if (game->platforms) { free(game->platforms); }
78     if (game->player) { free(game->player); }
79
80     free(game);
81 }
82
83 int game_render(const game_t *game, SDL_Renderer *renderer)
84 {
85     assert(game);
86     assert(renderer);
87
88     if (game->state == GAME_STATE_QUIT) {
89         return 0;
90     }
91
92     if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) < 0) {
93         throw_error(ERROR_TYPE_SDL2);
94         return -1;
95     }
96
97     if (SDL_RenderClear(renderer) < 0) {
98         throw_error(ERROR_TYPE_SDL2);
99         return -1;
100     }
101
102     if (render_player(game->player, renderer, game->camera) < 0) {
103         return -1;
104     }
105
106     if (render_platforms(game->platforms, renderer, game->camera) < 0) {
107         return -1;
108     }
109
110     SDL_RenderPresent(renderer);
111
112     return 0;
113 }
114
115 int game_update(game_t *game, Uint32 delta_time)
116 {
117     assert(game);
118     assert(delta_time > 0);
119
120     if (game->state == GAME_STATE_QUIT) {
121         return 0;
122     }
123
124     update_player(game->player, game->platforms, delta_time);
125     player_focus_camera(game->player, game->camera);
126
127     return 0;
128 }
129
130 int game_event(game_t *game, const SDL_Event *event)
131 {
132     assert(game);
133     assert(event);
134
135     if (game->state == GAME_STATE_QUIT) {
136         return 0;
137     }
138
139     switch (event->type) {
140     case SDL_QUIT:
141         game->state = GAME_STATE_QUIT;
142         break;
143
144     case SDL_KEYDOWN:
145         switch (event->key.keysym.sym) {
146         case SDLK_SPACE:
147             player_jump(game->player);
148             break;
149
150         case SDLK_q:
151             printf("Reloading the level from '%s'...", game->level_file_path);
152
153             destroy_platforms(game->platforms);
154             game->platforms = load_platforms_from_file(game->level_file_path);
155
156             if (game->platforms == NULL) {
157                 print_current_error_msg("Could not reload the level");
158                 game->state = GAME_STATE_QUIT;
159                 return -1;
160             }
161             break;
162         }
163         break;
164
165     case SDL_JOYBUTTONDOWN:
166         if (event->jbutton.button == 1) {
167             player_jump(game->player);
168         }
169         break;
170     }
171
172     return 0;
173 }
174
175 int game_input(game_t *game,
176                const Uint8 *const keyboard_state,
177                SDL_Joystick *the_stick_of_joy)
178 {
179     assert(game);
180     assert(keyboard_state);
181     assert(the_stick_of_joy);
182
183     if (game->state == GAME_STATE_QUIT) {
184         return 0;
185     }
186
187     if (keyboard_state[SDL_SCANCODE_A]) {
188         player_move_left(game->player);
189     } else if (keyboard_state[SDL_SCANCODE_D]) {
190         player_move_right(game->player);
191     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) < 0) {
192         player_move_left(game->player);
193     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) > 0) {
194         player_move_right(game->player);
195     } else {
196         player_stop(game->player);
197     }
198
199     return 0;
200 }
201
202 int is_game_over(const game_t *game)
203 {
204     return game->state == GAME_STATE_QUIT;
205 }