]> git.lizzy.rs Git - nothing.git/blob - src/game/level/background.c
(#157) Make const camera_t not able to render anything
[nothing.git] / src / game / level / background.c
1 #include <assert.h>
2
3 #include "game/level/background.h"
4 #include "math/rand.h"
5 #include "math/rect.h"
6 #include "system/lt.h"
7
8 #define BACKGROUND_CHUNK_COUNT 5
9 #define BACKGROUND_CHUNK_WIDTH 250.0f
10 #define BACKGROUND_CHUNK_HEIGHT 250.0f
11
12 static void chunk_of_point(point_t p, int *x, int *y);
13 int render_chunk(const background_t *background,
14                  camera_t *camera,
15                  int x, int y,
16                  color_t color,
17                  vec_t position,
18                  float parallax);
19
20 struct background_t
21 {
22     lt_t *lt;
23     color_t base_color;
24     vec_t position;
25     int debug_mode;
26 };
27
28 background_t *create_background(color_t base_color)
29 {
30     lt_t *lt = create_lt();
31     if (lt == NULL) {
32         return NULL;
33     }
34
35     background_t *background = PUSH_LT(lt, malloc(sizeof(background_t)), free);
36     if (background == NULL) {
37         RETURN_LT(lt, NULL);
38     }
39
40     background->base_color = base_color;
41     background->position = vec(0.0f, 0.0f);
42     background->debug_mode = 0;
43     background->lt = lt;
44
45     return background;
46 }
47
48 void destroy_background(background_t *background)
49 {
50     assert(background);
51     RETURN_LT0(background->lt);
52 }
53
54 /* TODO(#182): background chunks are randomly disappearing when the size of the window is less than size of the chunk  */
55 int background_render(const background_t *background,
56                       camera_t *camera)
57 {
58     assert(background);
59     assert(camera);
60
61     const rect_t view_port = camera_view_port(camera);
62     const vec_t position = vec(view_port.x, view_port.y);
63
64     for (int l = 0; l < 3; ++l) {
65         const float parallax = 1.0f - 0.2f * (float)l;
66
67         int min_x = 0, min_y = 0;
68         chunk_of_point(vec(view_port.x - position.x * parallax,
69                            view_port.y - position.y * parallax),
70                        &min_x, &min_y);
71
72         int max_x = 0, max_y = 0;
73         chunk_of_point(vec(view_port.x - position.x * parallax + view_port.w,
74                            view_port.y - position.y * parallax + view_port.h),
75                        &max_x, &max_y);
76
77         for (int x = min_x; x <= max_x; ++x) {
78             for (int y = min_y; y <= max_y; ++y) {
79                 if (render_chunk(
80                         background,
81                         camera,
82                         x, y,
83                         color_darker(background->base_color, 0.05f * (float)(l + 1)),
84                         position,
85                         parallax) < 0) {
86                     return -1;
87                 }
88             }
89         }
90     }
91
92     return 0;
93 }
94
95 /* Private Function */
96
97 static void chunk_of_point(point_t p, int *x, int *y)
98 {
99     assert(x);
100     assert(y);
101     *x = (int) (p.x / BACKGROUND_CHUNK_WIDTH);
102     *y = (int) (p.y / BACKGROUND_CHUNK_HEIGHT);
103 }
104
105 int render_chunk(const background_t *background,
106                  camera_t *camera,
107                  int chunk_x, int chunk_y,
108                  color_t color,
109                  vec_t position,
110                  float parallax)
111 {
112     (void) background;
113
114     if (background->debug_mode) {
115         return 0;
116     }
117
118     srand((unsigned int)(roundf((float)chunk_x + (float)chunk_y + parallax)));
119
120     for (size_t i = 0; i < BACKGROUND_CHUNK_COUNT; ++i) {
121         const float rect_x = rand_float_range((float) chunk_x * BACKGROUND_CHUNK_WIDTH,
122                                               (float) (chunk_x + 1) * BACKGROUND_CHUNK_WIDTH);
123         const float rect_y = rand_float_range((float) chunk_y * BACKGROUND_CHUNK_HEIGHT,
124                                               (float) (chunk_y + 1) * BACKGROUND_CHUNK_HEIGHT);
125         const float rect_w = rand_float_range(0.0f, BACKGROUND_CHUNK_WIDTH * 0.5f);
126         const float rect_h = rand_float_range(rect_w * 0.5f, rect_w * 1.5f);
127
128         if (camera_fill_rect(
129                 camera,
130                 rect(rect_x + position.x * parallax,
131                      rect_y + position.y * parallax,
132                      rect_w,
133                      rect_h),
134                 color) < 0) {
135             return -1;
136         }
137     }
138
139     return 0;
140 }
141
142 void background_toggle_debug_mode(background_t *background)
143 {
144     background->debug_mode = !background->debug_mode;
145 }