]> git.lizzy.rs Git - nothing.git/blob - src/game/level/lava.c
TODO(#449)
[nothing.git] / src / game / level / lava.c
1 #include <SDL2/SDL.h>
2 #include <assert.h>
3 #include <stdio.h>
4
5 #include "color.h"
6 #include "game/level/lava/wavy_rect.h"
7 #include "game/level/player/rigid_rect.h"
8 #include "lava.h"
9 #include "math/rect.h"
10 #include "system/error.h"
11 #include "system/lt.h"
12
13 #define LAVA_BOINGNESS 2500.0f
14
15 struct Lava {
16     Lt *lt;
17     size_t rects_count;
18     Wavy_rect **rects;
19 };
20
21 Lava *create_lava_from_stream(FILE *stream)
22 {
23     assert(stream);
24
25     Lt *lt = create_lt();
26     if (lt == NULL) {
27         return NULL;
28     }
29
30     Lava *lava = PUSH_LT(lt, malloc(sizeof(Lava)), free);
31     if (lava == NULL) {
32         throw_error(ERROR_TYPE_LIBC);
33         RETURN_LT(lt, NULL);
34     }
35
36     if (fscanf(stream, "%lu", &lava->rects_count) < 0) {
37         throw_error(ERROR_TYPE_LIBC);
38         RETURN_LT(lt, NULL);
39     }
40
41     lava->rects = PUSH_LT(lt, malloc(sizeof(Wavy_rect*) * lava->rects_count), free);
42     if (lava->rects == NULL) {
43         throw_error(ERROR_TYPE_LIBC);
44         RETURN_LT(lt, NULL);
45     }
46
47     for (size_t i = 0; i < lava->rects_count; ++i) {
48         lava->rects[i] = PUSH_LT(lt, create_wavy_rect_from_stream(stream), destroy_wavy_rect);
49         if (lava->rects[i] == NULL) {
50             RETURN_LT(lt, NULL);
51         }
52     }
53
54     lava->lt = lt;
55
56     return lava;
57 }
58
59 void destroy_lava(Lava *lava)
60 {
61     assert(lava);
62     RETURN_LT0(lava->lt);
63 }
64
65 /* TODO(#449): lava does not render its id in debug mode */
66 int lava_render(const Lava *lava,
67                 Camera *camera)
68 {
69     assert(lava);
70     assert(camera);
71
72     for (size_t i = 0; i < lava->rects_count; ++i) {
73         if (wavy_rect_render(lava->rects[i], camera) < 0) {
74             return -1;
75         }
76     }
77
78     return 0;
79 }
80
81 int lava_update(Lava *lava, float delta_time)
82 {
83     assert(lava);
84
85     for (size_t i = 0; i < lava->rects_count; ++i) {
86         if (wavy_rect_update(lava->rects[i], delta_time) < 0) {
87             return -1;
88         }
89     }
90
91     return 0;
92 }
93
94 bool lava_overlaps_rect(const Lava *lava,
95                         Rect rect)
96 {
97     assert(lava);
98
99     for (size_t i = 0; i < lava->rects_count; ++i) {
100         if (rects_overlap(wavy_rect_hitbox(lava->rects[i]), rect)) {
101             return true;
102         }
103     }
104
105     return 0;
106 }
107
108 void lava_float_rigid_rect(Lava *lava, Rigid_rect *object)
109 {
110     assert(lava);
111
112     const Rect object_hitbox = rigid_rect_hitbox(object);
113     for (size_t i = 0; i < lava->rects_count; ++i) {
114         const Rect lava_hitbox = wavy_rect_hitbox(lava->rects[i]);
115         if (rects_overlap(object_hitbox, lava_hitbox)) {
116             const Rect overlap_area = rects_overlap_area(object_hitbox, lava_hitbox);
117             const float k = overlap_area.w * overlap_area.h / (object_hitbox.w * object_hitbox.h);
118             rigid_rect_apply_force(
119                 object,
120                 vec(0.0f, -k * LAVA_BOINGNESS));
121             rigid_rect_damper(object, vec(0.0f, -0.9f));
122         }
123     }
124 }