]> git.lizzy.rs Git - nothing.git/blob - src/game/level/platforms.c
55e7a5c145916233d72a0154b1415db7b6f29dbc
[nothing.git] / src / game / level / platforms.c
1 #include <SDL2/SDL.h>
2 #include <assert.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "platforms.h"
8 #include "system/error.h"
9 #include "system/lt.h"
10 #include "system/lt/lt_adapters.h"
11 #include "system/line_stream.h"
12 #include "system/nth_alloc.h"
13
14 struct Platforms {
15     Lt *lt;
16
17     Rect *rects;
18     Color *colors;
19     size_t rects_size;
20 };
21
22 Platforms *create_platforms_from_line_stream(LineStream *line_stream)
23 {
24     assert(line_stream);
25
26     Lt *const lt = create_lt();
27     if (lt == NULL) {
28         return NULL;
29     }
30
31     Platforms *platforms = PUSH_LT(lt, nth_alloc(sizeof(Platforms)), free);
32     if (platforms == NULL) {
33         throw_error(ERROR_TYPE_LIBC);
34         RETURN_LT(lt, NULL);
35     }
36
37     platforms->rects_size = 0;
38     if (sscanf(
39             line_stream_next(line_stream),
40             "%lu",
41             &platforms->rects_size) == EOF) {
42         throw_error(ERROR_TYPE_LIBC);
43         RETURN_LT(lt, NULL);
44     }
45
46     platforms->rects = PUSH_LT(lt, nth_alloc(sizeof(Rect) * platforms->rects_size), free);
47     if (platforms->rects == NULL) {
48         throw_error(ERROR_TYPE_LIBC);
49         RETURN_LT(lt, NULL);
50     }
51
52     platforms->colors = PUSH_LT(lt, nth_alloc(sizeof(Color) * platforms->rects_size), free);
53     if (platforms->colors == NULL) {
54         throw_error(ERROR_TYPE_LIBC);
55         RETURN_LT(lt, NULL);
56     }
57
58     char color[7];
59     for (size_t i = 0; i < platforms->rects_size; ++i) {
60         if (sscanf(line_stream_next(line_stream),
61                    "%f%f%f%f%6s\n",
62                    &platforms->rects[i].x, &platforms->rects[i].y,
63                    &platforms->rects[i].w, &platforms->rects[i].h,
64                    color) < 0) {
65             throw_error(ERROR_TYPE_LIBC);
66             RETURN_LT(lt, NULL);
67         }
68         platforms->colors[i] = color_from_hexstr(color);
69     }
70
71     platforms->lt = lt;
72
73     return platforms;
74 }
75
76 void destroy_platforms(Platforms *platforms)
77 {
78     assert(platforms);
79     RETURN_LT0(platforms->lt);
80 }
81
82 int platforms_save_to_file(const Platforms *platforms,
83                            const char *filename)
84 {
85     assert(platforms);
86     assert(filename);
87
88     Lt *const lt = create_lt();
89     if (lt == NULL) {
90         return -1;
91     }
92
93     FILE *platforms_file = PUSH_LT(lt, fopen(filename, "w"), fclose_lt);
94
95     if (platforms_file == NULL) {
96         throw_error(ERROR_TYPE_LIBC);
97         RETURN_LT(lt, -1);
98     }
99
100     for (size_t i = 0; i < platforms->rects_size; ++i) {
101         if (fprintf(platforms_file, "%f %f %f %f\n",
102                     platforms->rects[i].x, platforms->rects[i].y,
103                     platforms->rects[i].w, platforms->rects[i].h) < 0) {
104             throw_error(ERROR_TYPE_LIBC);
105             RETURN_LT(lt, -1);
106         }
107     }
108
109     RETURN_LT(lt, 0);
110 }
111
112 Solid_ref platforms_as_solid(Platforms *platforms)
113 {
114     Solid_ref ref = {
115         .tag = SOLID_PLATFORMS,
116         .ptr = (void*)platforms
117     };
118
119     return ref;
120 }
121
122 /* TODO(#450): platforms do not render their ids in debug mode */
123 int platforms_render(const Platforms *platforms,
124                      Camera *camera)
125 {
126     for (size_t i = 0; i < platforms->rects_size; ++i) {
127         if (camera_fill_rect(
128                 camera,
129                 platforms->rects[i],
130                 platforms->colors[i]) < 0) {
131             throw_error(ERROR_TYPE_SDL2);
132             return -1;
133         }
134     }
135
136     return 0;
137 }
138
139 void platforms_touches_rect_sides(const Platforms *platforms,
140                                   Rect object,
141                                   int sides[RECT_SIDE_N])
142 {
143     assert(platforms);
144
145     for (size_t i = 0; i < platforms->rects_size; ++i) {
146         rect_object_impact(object, platforms->rects[i], sides);
147     }
148 }