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