-#include <assert.h>
+#include <stdio.h>
#include "game/level/background.h"
#include "math/rand.h"
#include "math/rect.h"
+#include "system/line_stream.h"
#include "system/lt.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
+#include "system/stacktrace.h"
-#define BACKGROUND_CHUNK_COUNT 10
-#define BACKGROUND_CHUNK_WIDTH 500.0f
-#define BACKGROUND_CHUNK_HEIGHT 500.0f
+#define BACKGROUND_CHUNK_COUNT 5
+#define BACKGROUND_CHUNK_WIDTH 250.0f
+#define BACKGROUND_CHUNK_HEIGHT 250.0f
-static void chunk_of_point(point_t p, int *x, int *y);
-int render_chunk(const background_t *background,
- const camera_t *camera,
+static void chunk_of_point(Point p, int *x, int *y);
+int render_chunk(const Background *background,
+ Camera *camera,
int x, int y,
- color_t color,
+ Color color,
+ Vec position,
float parallax);
-struct background_t
+struct Background
{
- lt_t *lt;
- color_t base_color;
- vec_t position;
+ Lt *lt;
+ Color base_color;
+ Vec position;
+ int debug_mode;
};
-background_t *create_background(color_t base_color)
+Background *create_background(Color base_color)
{
- lt_t *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
+ Lt *lt = create_lt();
- background_t *background = PUSH_LT(lt, malloc(sizeof(background_t)), free);
+ Background *background = PUSH_LT(lt, nth_calloc(1, sizeof(Background)), free);
if (background == NULL) {
RETURN_LT(lt, NULL);
}
background->base_color = base_color;
background->position = vec(0.0f, 0.0f);
+ background->debug_mode = 0;
background->lt = lt;
return background;
}
-void destroy_background(background_t *background)
+Background *create_background_from_line_stream(LineStream *line_stream)
{
- assert(background);
- RETURN_LT0(background->lt);
+ char color[7];
+ if (sscanf(line_stream_next(line_stream), "%6s", color) == EOF) {
+ log_fail("Could not read background's color\n");
+ return NULL;
+ }
+
+ return create_background(hexstr(color));
}
-int background_render(const background_t *background,
- const camera_t *camera)
+void destroy_background(Background *background)
{
- assert(background);
- assert(camera);
+ trace_assert(background);
+ RETURN_LT0(background->lt);
+}
- rect_t view_port = camera_view_port(camera);
+/* TODO(#182): background chunks are randomly disappearing when the size of the window is less than size of the chunk */
+int background_render(const Background *background,
+ Camera *camera)
+{
+ trace_assert(background);
+ trace_assert(camera);
- int min_x = 0, min_y = 0;
- chunk_of_point(vec(view_port.x, view_port.y), &min_x, &min_y);
+ if (camera_clear_background(
+ camera,
+ background->base_color) < 0) {
+ return -1;
+ }
- int max_x = 0, max_y = 0;
- chunk_of_point(vec(view_port.x + view_port.w,
- view_port.y + view_port.h), &max_x, &max_y);
+ const Rect view_port = camera_view_port(camera);
+ const Vec position = vec(view_port.x, view_port.y);
for (int l = 0; l < 3; ++l) {
+ const float parallax = 1.0f - 0.2f * (float)l;
+
+ int min_x = 0, min_y = 0;
+ chunk_of_point(vec(view_port.x - position.x * parallax,
+ view_port.y - position.y * parallax),
+ &min_x, &min_y);
+
+ int max_x = 0, max_y = 0;
+ chunk_of_point(vec(view_port.x - position.x * parallax + view_port.w,
+ view_port.y - position.y * parallax + view_port.h),
+ &max_x, &max_y);
+
for (int x = min_x; x <= max_x; ++x) {
for (int y = min_y; y <= max_y; ++y) {
- if (render_chunk(background, camera, x, y, color_darker(background->base_color, 0.2f * (float)l), 1.0f - 0.2f * (float)l) < 0) {
+ if (render_chunk(
+ background,
+ camera,
+ x, y,
+ color_darker(background->base_color, 0.05f * (float)(l + 1)),
+ position,
+ parallax) < 0) {
return -1;
}
}
return 0;
}
-void background_move_to(background_t *background,
- vec_t position)
-{
- background->position = position;
-}
-
/* Private Function */
-static void chunk_of_point(point_t p, int *x, int *y)
+static void chunk_of_point(Point p, int *x, int *y)
{
- assert(x);
- assert(y);
- *x = (int) roundf(p.x / BACKGROUND_CHUNK_WIDTH);
- *y = (int) roundf(p.y / BACKGROUND_CHUNK_HEIGHT);
+ trace_assert(x);
+ trace_assert(y);
+ *x = (int) (p.x / BACKGROUND_CHUNK_WIDTH);
+ *y = (int) (p.y / BACKGROUND_CHUNK_HEIGHT);
}
-int render_chunk(const background_t *background,
- const camera_t *camera,
- int x, int y,
- color_t color,
+int render_chunk(const Background *background,
+ Camera *camera,
+ int chunk_x, int chunk_y,
+ Color color,
+ Vec position,
float parallax)
{
- srand((unsigned int)(roundf((float)x + (float)y + parallax)));
+ (void) background;
+
+ if (background->debug_mode) {
+ return 0;
+ }
+
+ srand((unsigned int)(roundf((float)chunk_x + (float)chunk_y + parallax)));
for (size_t i = 0; i < BACKGROUND_CHUNK_COUNT; ++i) {
- const float rect_x = rand_float_range((float) x * BACKGROUND_CHUNK_WIDTH,
- (float) (x + 1) * BACKGROUND_CHUNK_WIDTH);
- const float rect_y = rand_float_range((float) y * BACKGROUND_CHUNK_HEIGHT,
- (float) (y + 1) * BACKGROUND_CHUNK_HEIGHT);
+ const float rect_x = rand_float_range((float) chunk_x * BACKGROUND_CHUNK_WIDTH,
+ (float) (chunk_x + 1) * BACKGROUND_CHUNK_WIDTH);
+ const float rect_y = rand_float_range((float) chunk_y * BACKGROUND_CHUNK_HEIGHT,
+ (float) (chunk_y + 1) * BACKGROUND_CHUNK_HEIGHT);
const float rect_w = rand_float_range(0.0f, BACKGROUND_CHUNK_WIDTH * 0.5f);
- const float rect_h = rand_float_range(0.0f, BACKGROUND_CHUNK_HEIGHT * 0.5f);
+ const float rect_h = rand_float_range(rect_w * 0.5f, rect_w * 1.5f);
if (camera_fill_rect(
camera,
- rect(rect_x + background->position.x * parallax,
- rect_y + background->position.y * parallax,
+ rect(rect_x + position.x * parallax,
+ rect_y + position.y * parallax,
rect_w,
rect_h),
color) < 0) {
return 0;
}
+
+void background_toggle_debug_mode(Background *background)
+{
+ background->debug_mode = !background->debug_mode;
+}