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