summaryrefslogtreecommitdiff
path: root/in_practice/breakout/level.c
blob: 619c05ffe7fbb6f5cea5dc49abd780833fa3b1f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "level.h"
#include "sys.h"
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <stdio.h>

struct level load_level(const char *dir, const char *filename, i32 width, i32 height)
{
	assert(filename);
	assert(width);
	assert(height);
	struct level 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;
}

struct level init_level(u8 *tiles, i32 rows, i32 cols, i32 width, i32 height)
{
	assert(tiles);
	struct level 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(struct object) * 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;
			struct object 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(struct level *level)
{
	free(level->tiles);
	level->tiles = 0;
	level->rows = 0;
	level->cols = 0;
}

void render_level(struct sprite_renderer renderer, struct level level)
{
	for (i32 i = 0; i < level.count; i++)
		if (!level.tiles[i].destroyed)
			render_object(renderer, level.tiles[i]);
}

i32 level_is_complete(struct level level)
{
	for (i32 i = 0; i < level.count; i++)
		if (!level.tiles[i].solid && !level.tiles[i].destroyed)
			return 0;
	return 1;
}