]> git.lizzy.rs Git - nothing.git/blob - src/game.c
Merge pull request #50 from tsoding/level-format-player-position
[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 (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) < 0) {
81         throw_error(ERROR_TYPE_SDL2);
82         return -1;
83     }
84
85     if (SDL_RenderClear(renderer) < 0) {
86         throw_error(ERROR_TYPE_SDL2);
87         return -1;
88     }
89
90     if (level_render(game->level, renderer) < 0) {
91         return -1;
92     }
93
94     SDL_RenderPresent(renderer);
95
96     return 0;
97 }
98
99 int game_update(game_t *game, Uint32 delta_time)
100 {
101     assert(game);
102     assert(delta_time > 0);
103
104     if (game->state == GAME_STATE_QUIT) {
105         return 0;
106     }
107
108     if (game->state == GAME_STATE_RUNNING) {
109         return level_update(game->level, delta_time);
110     }
111
112     return 0;
113 }
114
115
116 static int game_event_pause(game_t *game, const SDL_Event *event)
117 {
118     assert(game);
119     assert(event);
120
121     switch (event->type) {
122     case SDL_QUIT:
123         game->state = GAME_STATE_QUIT;
124         break;
125
126     case SDL_KEYDOWN:
127         switch (event->key.keysym.sym) {
128         case SDLK_p:
129             game->state = GAME_STATE_RUNNING;
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_q:
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(game->level_file_path));
160
161             if (game->level == NULL) {
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             break;
171
172         case SDLK_l:
173             level_toggle_debug_mode(game->level);
174             break;
175         }
176         break;
177
178     }
179
180     return level_event(game->level, event);
181 }
182
183 int game_event(game_t *game, const SDL_Event *event)
184 {
185     assert(game);
186     assert(event);
187
188     switch (game->state) {
189     case GAME_STATE_RUNNING:
190         return game_event_running(game, event);
191
192     case GAME_STATE_PAUSE:
193         return game_event_pause(game, event);
194
195     default: {}
196     }
197
198     return 0;
199 }
200
201
202 int game_input(game_t *game,
203                const Uint8 *const keyboard_state,
204                SDL_Joystick *the_stick_of_joy)
205 {
206     assert(game);
207     assert(keyboard_state);
208
209     if (game->state == GAME_STATE_QUIT || game->state == GAME_STATE_PAUSE) {
210         return 0;
211     }
212
213     return level_input(game->level, keyboard_state, the_stick_of_joy);
214 }
215
216 int is_game_over(const game_t *game)
217 {
218     return game->state == GAME_STATE_QUIT;
219 }