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