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