]> git.lizzy.rs Git - nothing.git/blob - src/game/level.c
(#1148) Disable pause mode after reloading the level
[nothing.git] / src / game / level.c
1 #include <SDL.h>
2 #include "system/stacktrace.h"
3
4 #include "color.h"
5 #include "game/camera.h"
6 #include "game/level.h"
7 #include "game/level/background.h"
8 #include "game/level/boxes.h"
9 #include "game/level/goals.h"
10 #include "game/level/labels.h"
11 #include "game/level/lava.h"
12 #include "game/level/platforms.h"
13 #include "game/level/player.h"
14 #include "game/level/regions.h"
15 #include "game/level/rigid_bodies.h"
16 #include "game/level_metadata.h"
17 #include "game/level/level_editor/rect_layer.h"
18 #include "game/level/level_editor/point_layer.h"
19 #include "game/level/level_editor/player_layer.h"
20 #include "game/level/level_editor/label_layer.h"
21 #include "game/level/level_editor/background_layer.h"
22 #include "system/line_stream.h"
23 #include "system/log.h"
24 #include "system/lt.h"
25 #include "system/nth_alloc.h"
26 #include "system/str.h"
27 #include "game/level/level_editor.h"
28 #include "ui/console.h"
29
30 #define LEVEL_GRAVITY 1500.0f
31 #define JOYSTICK_THRESHOLD 1000
32
33 typedef enum {
34     LEVEL_STATE_IDLE = 0,
35     LEVEL_STATE_PAUSE
36 } LevelState;
37
38 struct Level
39 {
40     Lt *lt;
41
42     LevelState state;
43     LevelMetadata *metadata;
44     Background background;
45     RigidBodies *rigid_bodies;
46     Player *player;
47     Platforms *platforms;
48     Goals *goals;
49     Lava *lava;
50     Platforms *back_platforms;
51     Boxes *boxes;
52     Labels *labels;
53     Regions *regions;
54 };
55
56 Level *create_level_from_level_editor(const LevelEditor *level_editor)
57 {
58     trace_assert(level_editor);
59
60     Lt *lt = create_lt();
61
62     Level *level = PUSH_LT(
63         lt,
64         nth_calloc(1, sizeof(Level)),
65         free);
66     if (level == NULL) {
67         RETURN_LT(lt, NULL);
68     }
69     level->lt = lt;
70
71     level->background = create_background(
72         color_picker_rgba(
73             &level_editor->background_layer.color_picker));
74
75     level->rigid_bodies = PUSH_LT(lt, create_rigid_bodies(1024), destroy_rigid_bodies);
76     if (level->rigid_bodies == NULL) {
77         RETURN_LT(lt, NULL);
78     }
79
80     level->player = PUSH_LT(
81         lt,
82         create_player_from_player_layer(
83             &level_editor->player_layer,
84             level->rigid_bodies),
85         destroy_player);
86     if (level->player == NULL) {
87         RETURN_LT(lt, NULL);
88     }
89
90     level->platforms = PUSH_LT(
91         lt,
92         create_platforms_from_rect_layer(level_editor->platforms_layer),
93         destroy_platforms);
94     if (level->platforms == NULL) {
95         RETURN_LT(lt, NULL);
96     }
97
98     level->goals = PUSH_LT(
99         lt,
100         create_goals_from_point_layer(level_editor->goals_layer),
101         destroy_goals);
102     if (level->goals == NULL) {
103         RETURN_LT(lt, NULL);
104     }
105
106     level->lava = PUSH_LT(
107         lt,
108         create_lava_from_rect_layer(level_editor->lava_layer),
109         destroy_lava);
110     if (level->lava == NULL) {
111         RETURN_LT(lt, NULL);
112     }
113
114     level->back_platforms = PUSH_LT(
115         lt,
116         create_platforms_from_rect_layer(level_editor->back_platforms_layer),
117         destroy_platforms);
118     if (level->back_platforms == NULL) {
119         RETURN_LT(lt, NULL);
120     }
121
122     level->boxes = PUSH_LT(
123         lt,
124         create_boxes_from_rect_layer(level_editor->boxes_layer, level->rigid_bodies),
125         destroy_boxes);
126     if (level->boxes == NULL) {
127         RETURN_LT(lt, NULL);
128     }
129
130     level->labels = PUSH_LT(
131         lt,
132         create_labels_from_label_layer(level_editor->label_layer),
133         destroy_labels);
134     if (level->labels == NULL) {
135         RETURN_LT(lt, NULL);
136     }
137
138     level->regions = PUSH_LT(
139         lt,
140         create_regions_from_rect_layer(
141             level_editor->regions_layer,
142             level->labels,
143             level->goals),
144         destroy_regions);
145     if (level->regions == NULL) {
146         RETURN_LT(lt, NULL);
147     }
148
149     return level;
150 }
151
152 void destroy_level(Level *level)
153 {
154     trace_assert(level);
155     RETURN_LT0(level->lt);
156 }
157
158 int level_render(const Level *level, const Camera *camera)
159 {
160     trace_assert(level);
161
162     if (background_render(&level->background, camera) < 0) {
163         return -1;
164     }
165
166     if (platforms_render(level->back_platforms, camera) < 0) {
167         return -1;
168     }
169
170     if (player_render(level->player, camera) < 0) {
171         return -1;
172     }
173
174     if (boxes_render(level->boxes, camera) < 0) {
175         return -1;
176     }
177
178     if (lava_render(level->lava, camera) < 0) {
179         return -1;
180     }
181
182     if (platforms_render(level->platforms, camera) < 0) {
183         return -1;
184     }
185
186     if (goals_render(level->goals, camera) < 0) {
187         return -1;
188     }
189
190     if (labels_render(level->labels, camera) < 0) {
191         return -1;
192     }
193
194     if (regions_render(level->regions, camera) < 0) {
195         return -1;
196     }
197
198     return 0;
199 }
200
201 int level_update(Level *level, float delta_time)
202 {
203     trace_assert(level);
204     trace_assert(delta_time > 0);
205
206     if (level->state == LEVEL_STATE_PAUSE) {
207         return 0;
208     }
209
210     boxes_float_in_lava(level->boxes, level->lava);
211     rigid_bodies_apply_omniforce(level->rigid_bodies, vec(0.0f, LEVEL_GRAVITY));
212
213     boxes_update(level->boxes, delta_time);
214     player_update(level->player, delta_time);
215
216     rigid_bodies_collide(level->rigid_bodies, level->platforms);
217
218     player_die_from_lava(level->player, level->lava);
219     regions_player_enter(level->regions, level->player);
220     regions_player_leave(level->regions, level->player);
221
222     goals_update(level->goals, delta_time);
223     lava_update(level->lava, delta_time);
224     labels_update(level->labels, delta_time);
225
226     return 0;
227 }
228
229 static
230 int level_event_idle(Level *level, const SDL_Event *event,
231                      Camera *camera, Sound_samples *sound_samples)
232 {
233     trace_assert(level);
234
235     switch (event->type) {
236     case SDL_KEYDOWN:
237         switch (event->key.keysym.sym) {
238         case SDLK_w:
239         case SDLK_UP:
240         case SDLK_SPACE: {
241             player_jump(level->player);
242         } break;
243
244         case SDLK_p: {
245             level->state = LEVEL_STATE_PAUSE;
246             camera->blackwhite_mode = true;
247             sound_samples_toggle_pause(sound_samples);
248         } break;
249
250         case SDLK_l: {
251             camera_toggle_debug_mode(camera);
252         } break;
253         }
254         break;
255
256     case SDL_JOYBUTTONDOWN:
257         if (event->jbutton.button == 1) {
258             player_jump(level->player);
259         }
260         break;
261     }
262
263     return 0;
264 }
265
266 static
267 int level_event_pause(Level *level, const SDL_Event *event,
268                       Camera *camera, Sound_samples *sound_samples)
269 {
270     trace_assert(level);
271
272     switch (event->type) {
273     case SDL_KEYDOWN: {
274         switch (event->key.keysym.sym) {
275         case SDLK_p: {
276             level->state = LEVEL_STATE_IDLE;
277             camera->blackwhite_mode = false;
278             sound_samples_toggle_pause(sound_samples);
279         } break;
280         }
281     } break;
282     }
283
284     return 0;
285 }
286
287 int level_event(Level *level, const SDL_Event *event,
288                 Camera *camera, Sound_samples *sound_samples)
289 {
290     trace_assert(level);
291     trace_assert(event);
292
293     switch (level->state) {
294     case LEVEL_STATE_IDLE: {
295         return level_event_idle(level, event, camera, sound_samples);
296     } break;
297
298     case LEVEL_STATE_PAUSE: {
299         return level_event_pause(level, event, camera, sound_samples);
300     } break;
301     }
302
303     return 0;
304 }
305
306 int level_input(Level *level,
307                 const Uint8 *const keyboard_state,
308                 SDL_Joystick *the_stick_of_joy)
309 {
310     trace_assert(level);
311     trace_assert(keyboard_state);
312
313     if (level->state == LEVEL_STATE_PAUSE) {
314         return 0;
315     }
316
317     if (keyboard_state[SDL_SCANCODE_A] || keyboard_state[SDL_SCANCODE_LEFT]) {
318         player_move_left(level->player);
319     } else if (keyboard_state[SDL_SCANCODE_D] || keyboard_state[SDL_SCANCODE_RIGHT]) {
320         player_move_right(level->player);
321     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) < -JOYSTICK_THRESHOLD) {
322         player_move_left(level->player);
323     } else if (the_stick_of_joy && SDL_JoystickGetAxis(the_stick_of_joy, 0) > JOYSTICK_THRESHOLD) {
324         player_move_right(level->player);
325     } else {
326         player_stop(level->player);
327     }
328
329     return 0;
330 }
331
332 int level_sound(Level *level, Sound_samples *sound_samples)
333 {
334     if (level->state == LEVEL_STATE_PAUSE) {
335         return 0;
336     }
337
338     if (goals_sound(level->goals, sound_samples) < 0) {
339         return -1;
340     }
341
342     if (player_sound(level->player, sound_samples) < 0) {
343         return -1;
344     }
345
346     return 0;
347 }
348
349 int level_enter_camera_event(Level *level, Camera *camera)
350 {
351     if (level->state == LEVEL_STATE_PAUSE) {
352         return 0;
353     }
354
355     player_focus_camera(level->player, camera);
356     camera_scale(camera, 1.0f);
357
358     goals_cue(level->goals, camera);
359     goals_checkpoint(level->goals, level->player);
360     labels_enter_camera_event(level->labels, camera);
361     return 0;
362 }
363
364 void level_disable_pause_mode(Level *level, Camera *camera,
365                               Sound_samples *sound_samples)
366 {
367     trace_assert(level);
368     trace_assert(camera);
369     trace_assert(sound_samples);
370     level->state = LEVEL_STATE_IDLE;
371     camera->blackwhite_mode = false;
372     sound_samples_toggle_pause(sound_samples);
373 }