summaryrefslogtreecommitdiff
path: root/in_practice/breakout/level.c
diff options
context:
space:
mode:
Diffstat (limited to 'in_practice/breakout/level.c')
-rw-r--r--in_practice/breakout/level.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/in_practice/breakout/level.c b/in_practice/breakout/level.c
new file mode 100644
index 0000000..6134959
--- /dev/null
+++ b/in_practice/breakout/level.c
@@ -0,0 +1,128 @@
+#include "level.h"
+#include "sys.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+
+level_t load_level(const char *dir, const char *filename, i32 width, i32 height)
+{
+ assert(filename);
+ assert(width);
+ assert(height);
+ level_t level = {0};
+ char path[512] = {0};
+ snprintf(path, 512, "%s/%s", (dir ? dir : "."), filename);
+ u8 *data = (u8 *)read_entire_file(path);
+ if (!data) {
+ info("failed to read \"%s\"", path);
+ return level;
+ }
+ i32 rows = 0, col = 0, cols = 0;
+ for (u8 *c = data; *c; c++) {
+ if (isdigit(*c)) {
+ col++;
+ } else if (*c == '\n') {
+ if (cols && col != cols) {
+ info("row %d, columns differ (previous %d)", rows, cols);
+ free(data);
+ return level;
+ }
+ rows++;
+ cols = col;
+ col = 0;
+ }
+ }
+ if (!rows) {
+ info("invalid rows number");
+ return level;
+ }
+ if (!cols) {
+ info("invalid columns number");
+ return level;
+ }
+ u8 *tiles = malloc(sizeof(u8) * rows * cols);
+ i32 i = 0;
+ for (u8 *c = data; *c; c++)
+ if (isdigit(*c))
+ tiles[i++] = *c - '0';
+ level = init_level(tiles, rows, cols, width, height);
+ free(tiles);
+ free(data);
+ info("level \"%s\" loaded successfully", path);
+ return level;
+}
+
+level_t init_level(u8 *tiles, i32 rows, i32 cols, i32 width, i32 height)
+{
+ assert(tiles);
+ level_t level = {0};
+ level.rows = rows;
+ level.cols = cols;
+ f32 tile_width = width / cols;
+ f32 tile_height = height / rows;
+ v2 size = {tile_width, tile_height};
+ for (i32 i = 0; i < rows * cols; i++)
+ if (tiles[i])
+ level.count++;
+ level.tiles = malloc(sizeof(object_t) * level.count);
+ i32 i = 0;
+ for (i32 row = 0; row < rows; row++) {
+ for (i32 col = 0; col < cols; col++) {
+ u8 *tile = tiles + col + row * cols;
+ if (!*tile)
+ continue;
+ object_t obj = {0};
+ obj.pos = (v2){tile_width * col, tile_height * row};
+ obj.size = size;
+ obj.texture = get_texture_id("solid");
+ if (*tile == 1) {
+ obj.color = (v3){0.8f, 0.8f, 0.7f};
+ obj.solid = 1;
+ } else if (*tile > 1) {
+ v3 color = {1.0f, 1.0f, 1.0f};
+ switch (*tile) {
+ case 2:
+ color = (v3){0.2f, 0.6f, 1.0f};
+ break;
+ case 3:
+ color = (v3){0.0f, 0.7f, 0.0f};
+ break;
+ case 4:
+ color = (v3){0.8f, 0.8f, 0.4f};
+ break;
+ case 5:
+ color = (v3){1.0f, 0.5f, 0.0f};
+ break;
+ }
+ obj.color = color;
+ obj.texture = get_texture_id("block");
+ }
+ level.tiles[i++] = obj;
+ }
+ }
+ return level;
+}
+
+void clear_level(level_t *level)
+{
+ free(level->tiles);
+ level->tiles = 0;
+ level->rows = 0;
+ level->cols = 0;
+}
+
+void render_level(sprite_renderer_t renderer, level_t level)
+{
+ for (i32 i = 0; i < level.count; i++)
+ if (!level.tiles[i].destroyed)
+ render_object(renderer, level.tiles[i]);
+}
+
+i32 level_is_completed(level_t level)
+{
+ for (i32 i = 0; i < level.count; i++)
+ if (!level.tiles[i].solid && !level.tiles[i].destroyed)
+ return 0;
+ return 1;
+}