]> git.lizzy.rs Git - nothing.git/blob - src/game/level/background.c
(#174) Don't round up the chunk coordinates
[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 int background_render(const background_t *background,
53                       const camera_t *camera)
54 {
55     assert(background);
56     assert(camera);
57
58     const rect_t view_port = camera_view_port(camera);
59     const vec_t position = vec(view_port.x, view_port.y);
60
61     for (int l = 0; l < 3; ++l) {
62         const float parallax = 1.0f - 0.2f * (float)l;
63
64         int min_x = 0, min_y = 0;
65         chunk_of_point(vec(view_port.x - position.x * parallax,
66                            view_port.y - position.y * parallax),
67                        &min_x, &min_y);
68
69         int max_x = 0, max_y = 0;
70         chunk_of_point(vec(view_port.x - position.x * parallax + view_port.w,
71                            view_port.y - position.y * parallax + view_port.h),
72                        &max_x, &max_y);
73
74         for (int x = min_x; x <= max_x; ++x) {
75             for (int y = min_y; y <= max_y; ++y) {
76                 if (render_chunk(
77                         background,
78                         camera,
79                         x, y,
80                         color_darker(background->base_color, 0.2f * (float)l),
81                         position,
82                         parallax) < 0) {
83                     return -1;
84                 }
85             }
86         }
87     }
88
89     return 0;
90 }
91
92 /* Private Function */
93
94 static void chunk_of_point(point_t p, int *x, int *y)
95 {
96     assert(x);
97     assert(y);
98     *x = (int) (p.x / BACKGROUND_CHUNK_WIDTH);
99     *y = (int) (p.y / BACKGROUND_CHUNK_HEIGHT);
100 }
101
102 int render_chunk(const background_t *background,
103                  const camera_t *camera,
104                  int x, int y,
105                  color_t color,
106                  vec_t position,
107                  float parallax)
108 {
109     (void) background;
110
111     srand((unsigned int)(roundf((float)x + (float)y + parallax)));
112
113     for (size_t i = 0; i < BACKGROUND_CHUNK_COUNT; ++i) {
114         const float rect_x = rand_float_range((float) x * BACKGROUND_CHUNK_WIDTH,
115                                               (float) (x + 1) * BACKGROUND_CHUNK_WIDTH);
116         const float rect_y = rand_float_range((float) y * BACKGROUND_CHUNK_HEIGHT,
117                                               (float) (y + 1) * BACKGROUND_CHUNK_HEIGHT);
118         const float rect_w = rand_float_range(0.0f, BACKGROUND_CHUNK_WIDTH * 0.5f);
119         const float rect_h = rand_float_range(0.0f, BACKGROUND_CHUNK_HEIGHT * 0.5f);
120
121         if (camera_fill_rect(
122                 camera,
123                 rect(rect_x + position.x * parallax,
124                      rect_y + position.y * parallax,
125                      rect_w,
126                      rect_h),
127                 color) < 0) {
128             return -1;
129         }
130     }
131
132     return 0;
133 }