]> git.lizzy.rs Git - nothing.git/blob - src/platforms.c
Merge pull request #153 from tsoding/152
[nothing.git] / src / platforms.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5
6 #include <SDL2/SDL.h>
7
8 #include "./platforms.h"
9 #include "./error.h"
10 #include "./lt.h"
11
12 struct platforms_t {
13     lt_t *lt;
14
15     rect_t *rects;
16     color_t *colors;
17     size_t rects_size;
18 };
19
20 platforms_t *create_platforms_from_stream(FILE *stream)
21 {
22     assert(stream);
23
24     lt_t *const lt = create_lt();
25     if (lt == NULL) {
26         return NULL;
27     }
28
29     platforms_t *platforms = PUSH_LT(lt, malloc(sizeof(platforms_t)), 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_t) * 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_t) * 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_t *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_t *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_t *platforms)
91 {
92     assert(platforms);
93     RETURN_LT0(platforms->lt);
94 }
95
96 int platforms_save_to_file(const platforms_t *platforms,
97                            const char *filename)
98 {
99     assert(platforms);
100     assert(filename);
101
102     lt_t *const lt = create_lt();
103     if (lt == NULL) {
104         return -1;
105     }
106
107     FILE *platforms_file = PUSH_LT(lt, fopen(filename, "w"), fclose);
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 int platforms_render(const platforms_t *platforms,
127                      SDL_Renderer *renderer,
128                      const camera_t *camera)
129 {
130     for (size_t i = 0; i < platforms->rects_size; ++i) {
131         if (camera_fill_rect(
132                 camera,
133                 renderer,
134                 platforms->rects[i],
135                 platforms->colors[i]) < 0) {
136             throw_error(ERROR_TYPE_SDL2);
137             return -1;
138         }
139     }
140
141     return 0;
142 }
143
144 void platforms_rect_object_collide(const platforms_t *platforms,
145                                    rect_t object,
146                                    int sides[RECT_SIDE_N])
147 {
148     assert(platforms);
149
150     memset(sides, 0, sizeof(int) * RECT_SIDE_N);
151
152     for (size_t i = 0; i < platforms->rects_size; ++i) {
153         rect_object_impact(&object, &platforms->rects[i], sides);
154     }
155 }