]> git.lizzy.rs Git - nothing.git/blob - src/game/level/platforms.c
08acf507f9355c8a11012388b71284fc4ebbe13a
[nothing.git] / src / game / level / platforms.c
1 #include <SDL.h>
2 #include "system/stacktrace.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7
8 #include "platforms.h"
9 #include "system/lt.h"
10 #include "system/nth_alloc.h"
11 #include "system/log.h"
12 #include "game/level/level_editor/rect_layer.h"
13 #include "math/extrema.h"
14
15 struct Platforms {
16     Lt *lt;
17
18     Rect *rects;
19     Color *colors;
20     int *hiding;
21     size_t rects_size;
22 };
23
24 Platforms *create_platforms_from_rect_layer(const RectLayer *layer)
25 {
26     trace_assert(layer);
27
28     Lt *lt = create_lt();
29
30     Platforms *platforms = PUSH_LT(
31         lt,
32         nth_calloc(1, sizeof(Platforms)),
33         free);
34     if (platforms == NULL) {
35         RETURN_LT(lt, NULL);
36     }
37     platforms->lt = lt;
38
39     platforms->rects_size = rect_layer_count(layer);
40
41     platforms->rects = PUSH_LT(lt, nth_calloc(1, sizeof(Rect) * platforms->rects_size), free);
42     if (platforms->rects == NULL) {
43         RETURN_LT(lt, NULL);
44     }
45     memcpy(platforms->rects, rect_layer_rects(layer), sizeof(Rect) * platforms->rects_size);
46
47
48     platforms->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * platforms->rects_size), free);
49     if (platforms->colors == NULL) {
50         RETURN_LT(lt, NULL);
51     }
52     memcpy(platforms->colors, rect_layer_colors(layer), sizeof(Color) * platforms->rects_size);
53
54     platforms->hiding = PUSH_LT(lt, nth_calloc(1, sizeof(int) * platforms->rects_size), free);
55     if (platforms->hiding == NULL) {
56         RETURN_LT(lt, NULL);
57     }
58     memset(platforms->hiding, 0, sizeof(int) * platforms->rects_size);
59
60     return platforms;
61 }
62
63 void destroy_platforms(Platforms *platforms)
64 {
65     trace_assert(platforms);
66     RETURN_LT0(platforms->lt);
67 }
68
69 int platforms_render(const Platforms *platforms,
70                      const Camera *camera)
71 {
72     for (size_t i = 0; i < platforms->rects_size; ++i) {
73         Rect platform_rect = platforms->rects[i];
74         if (camera_fill_rect(
75                 camera,
76                 platform_rect,
77                 platforms->colors[i]) < 0) {
78             return -1;
79         }
80
81         char debug_text[256];
82         snprintf(debug_text, 256,
83             "id:%zd\n"
84             "x:%.2f\n"
85             "y:%.2f\n"
86             "w:%.2f\n"
87             "h:%.2f\n",
88             i, platform_rect.x, platform_rect.y, platform_rect.w, platform_rect.h);
89
90         Vec2f text_pos = (Vec2f){.x = platform_rect.x, .y = platform_rect.y};
91         Rect text_rect = sprite_font_boundary_box(text_pos, vec(2.0f, 2.0f), debug_text);
92
93         Rect world_viewport = camera_view_port(camera);
94         Rect viewport = camera_view_port_screen(camera);
95
96         if (rects_overlap(
97                 camera_rect(
98                     camera,
99                     platform_rect),
100                 viewport) &&
101             camera_is_point_visible(
102                 camera,
103                 text_pos) == false) {
104             if (platform_rect.w > text_rect.w){
105                 text_pos.x = fmaxf(fminf(world_viewport.x, platform_rect.x + platform_rect.w - text_rect.w),
106                                    platform_rect.x);
107             }
108             if (platform_rect.h > text_rect.h){
109                 text_pos.y = fmaxf(fminf(world_viewport.y, platform_rect.y + platform_rect.h - text_rect.h),
110                                    platform_rect.y);
111             }
112         }
113
114         if (camera_render_debug_text(
115                 camera,
116                 debug_text,
117                 text_pos) < 0) {
118             return -1;
119         }
120     }
121
122     return 0;
123 }
124
125 void platforms_touches_rect_sides(const Platforms *platforms,
126                                   Rect object,
127                                   int sides[RECT_SIDE_N])
128 {
129     trace_assert(platforms);
130
131     for (size_t i = 0; i < platforms->rects_size; ++i) {
132         rect_object_impact(object, platforms->rects[i], sides);
133     }
134 }
135
136 Vec2f platforms_snap_rect(const Platforms *platforms,
137                          Rect *object)
138 {
139     trace_assert(platforms);
140
141     Vec2f result = vec(1.0f, 1.0f);
142     for (size_t i = 0; i < platforms->rects_size; ++i) {
143         if (rects_overlap(platforms->rects[i], *object)) {
144             // TODO(#1161): can we reuse the Level Editor snapping mechanism in physics snapping
145             result = vec_entry_mult(result, rect_snap(platforms->rects[i], object));
146         }
147     }
148
149     return result;
150 }
151
152 #define HIDING_SPEED 2.0f
153
154 void platforms_update(Platforms *platforms, float dt)
155 {
156     trace_assert(platforms);
157     for (size_t i = 0; i < platforms->rects_size; ++i) {
158         if (platforms->hiding[i]) {
159             if (platforms->colors[i].a > 0.0f) {
160                 platforms->colors[i].a =
161                     fmaxf(0.0f, platforms->colors[i].a - HIDING_SPEED * dt);
162             } else {
163                 platforms->hiding[i] = 0;
164             }
165         }
166     }
167 }
168
169 void platforms_hide_platform_at(const Platforms *platforms,
170                                 Vec2f position)
171 {
172     trace_assert(platforms);
173
174     for (size_t i = 0; i < platforms->rects_size; ++i) {
175         if (rect_contains_point(platforms->rects[i], position)) {
176             platforms->hiding[i] = 1;
177         }
178     }
179 }