]> git.lizzy.rs Git - nothing.git/blob - src/game.c
Merge pull request #139 from tsoding/134
[nothing.git] / src / game.c
1 #include <stdio.h>
2 #include <assert.h>
3 #include <SDL2/SDL.h>
4 #include <SDL2/SDL_mixer.h>
5
6 #include "./player.h"
7 #include "./platforms.h"
8 #include "./game.h"
9 #include "./error.h"
10 #include "./level.h"
11 #include "./sound_medium.h"
12 #include "./lt.h"
13
14 typedef enum game_state_t {
15     GAME_STATE_RUNNING = 0,
16     GAME_STATE_PAUSE,
17     GAME_STATE_QUIT,
18
19     GAME_STATE_N
20 } game_state_t;
21
22 typedef struct game_t {
23     lt_t *lt;
24
25     game_state_t state;
26     level_t *level;
27     char *level_file_path;
28     sound_medium_t *sound_medium;
29 } game_t;
30
31 game_t *create_game(const char *level_file_path, sound_medium_t *sound_medium)
32 {
33     assert(level_file_path);
34
35     lt_t *const lt = create_lt();
36     if (lt == NULL) {
37         return NULL;
38     }
39
40     game_t *game = PUSH_LT(lt, malloc(sizeof(game_t)), free);
41     if (game == NULL) {
42         throw_error(ERROR_TYPE_LIBC);
43         RETURN_LT(lt, NULL);
44     }
45
46     game->level = PUSH_LT(
47         lt,
48         create_level_from_file(level_file_path),
49         destroy_level);
50     if (game->level == NULL) {
51         RETURN_LT(lt, NULL);
52     }
53
54     game->level_file_path = PUSH_LT(lt, malloc(sizeof(char) * (strlen(level_file_path) + 1)), free);
55     if (game->level_file_path == NULL) {
56         throw_error(ERROR_TYPE_LIBC);
57         RETURN_LT(lt, NULL);
58     }
59
60     strcpy(game->level_file_path, level_file_path);
61
62     game->state = GAME_STATE_RUNNING;
63     game->sound_medium = sound_medium;
64     game->lt = lt;
65
66     return game;
67 }
68
69 void destroy_game(game_t *game)
70 {
71     assert(game);
72     RETURN_LT0(game->lt);
73 }
74
75 int game_render(const game_t *game, SDL_Renderer *renderer)
76 {
77     assert(game);
78     assert(renderer);
79
80     if (game->state == GAME_STATE_QUIT) {
81         return 0;
82     }
83
84     if (level_render(game->level, renderer) < 0) {
85         return -1;
86     }
87
88     SDL_RenderPresent(renderer);
89
90     return 0;
91 }
92
93 int game_sound(game_t *game)
94 {
95     return level_sound(game->level, game->sound_medium);
96 }
97
98 int game_update(game_t *game, Uint32 delta_time)
99 {
100     assert(game);
101     assert(delta_time > 0);
102
103     if (game->state == GAME_STATE_QUIT) {
104         return 0;
105     }
106
107     if (game->state == GAME_STATE_RUNNING) {
108         return level_update(game->level, delta_time);
109     }
110
111     return 0;
112 }
113
114
115 static int game_event_pause(game_t *game, const SDL_Event *event)
116 {
117     assert(game);
118     assert(event);
119
120     switch (event->type) {
121     case SDL_QUIT:
122         game->state = GAME_STATE_QUIT;
123         break;
124
125     case SDL_KEYDOWN:
126         switch (event->key.keysym.sym) {
127         case SDLK_p:
128             game->state = GAME_STATE_RUNNING;
129             level_toggle_pause_mode(game->level);
130             break;
131         case SDLK_l:
132             level_toggle_debug_mode(game->level);
133             break;
134         }
135         break;
136     }
137
138     return level_event(game->level, event);
139 }
140
141 static int game_event_running(game_t *game, const SDL_Event *event)
142 {
143     assert(game);
144     assert(event);
145
146     switch (event->type) {
147     case SDL_QUIT:
148         game->state = GAME_STATE_QUIT;
149         break;
150
151     case SDL_KEYDOWN:
152         switch (event->key.keysym.sym) {
153         case SDLK_r:
154             printf("Reloading the level from '%s'...\n", game->level_file_path);
155
156             game->level = RESET_LT(
157                 game->lt,
158                 game->level,
159                 create_level_from_file(
160                     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 }