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