diff options
Diffstat (limited to 'in_practice/breakout/level.c')
-rw-r--r-- | in_practice/breakout/level.c | 128 |
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; +} |