Simplify world types

master
Louis Pearson 2022-08-04 13:11:20 -06:00
parent 8c7a6b096f
commit 0c79bfe575
5 changed files with 85 additions and 96 deletions

View File

@ -32,9 +32,11 @@ pub fn extractLevel(opt: Options) !void {
const level = opt.level;
const tileset = opt.tileset;
const tiles = level.tiles orelse return error.NullTiles;
const width = level.width;
const height = @divExact(@intCast(u16, level.tiles.len), level.width);
const size = level.tiles.len;
const height = @divExact(@intCast(u16, tiles.len), level.width);
const size = tiles.len;
map.map_size = .{ level.width, height };
circuit.map_size = .{ level.width, height };
@ -45,14 +47,17 @@ pub fn extractLevel(opt: Options) !void {
var circuit_map = try alloc.alloc(CircuitType, size);
defer alloc.free(circuit_map);
for (level.tiles) |tile, i| {
if (tile.is_tile) {
auto_map[i] = false;
map.tiles[i] = tile.data.tile;
circuit_map[i] = .None;
} else {
auto_map[i] = tile.data.flags.solid;
circuit_map[i] = @intToEnum(CircuitType, tile.data.flags.circuit);
for (tiles) |data, i| {
switch (data) {
.tile => |tile| {
auto_map[i] = false;
map.tiles[i] = tile;
circuit_map[i] = .None;
},
.flags => |flags| {
auto_map[i] = flags.solid;
circuit_map[i] = @intToEnum(CircuitType, flags.circuit);
},
}
}

View File

@ -42,6 +42,7 @@ export fn update() void {
// error.OutOfBounds => showErr(@errorName(e)),
error.EndOfStream => showErr(@errorName(e)),
error.OutOfMemory => showErr(@errorName(e)),
error.NullTiles => showErr(@errorName(e)),
},
}
}

View File

@ -11,7 +11,7 @@ const util = @import("util.zig");
const Vec2 = w4.Vec2;
var fba_buf: [1024]u8 = undefined;
var fba_buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&fba_buf);
var alloc = fba.allocator();
@ -49,11 +49,9 @@ pub fn start() !void {
};
const world_reader = stream.reader();
const header = try world.LevelHeader.read(world_reader);
var tile_buf: [4096]world.TileStore = undefined;
try header.readTiles(world_reader, &tile_buf);
const level = world.Level.init(header, &tile_buf);
var level = try world.Level.read(world_reader);
var level_buf = try alloc.alloc(world.TileData, level.size);
try level.readTiles(world_reader, level_buf);
try extract.extractLevel(.{
.alloc = frame_alloc,

View File

@ -16,75 +16,32 @@ pub const CircuitType = enum(u4) {
Source = 9,
};
pub const TileData = union {
pub const TileData = union(enum) {
tile: u7,
flags: struct {
solid: bool,
circuit: u4,
},
};
pub const TileStore = struct {
is_tile: bool,
data: TileData,
pub fn toByte(store: TileStore) u8 {
if (store.is_tile) {
return 1 | (store.data.tile << 1);
} else {
return (@intCast(u7, @boolToInt(store.data.flags.solid)) << 1) | (@intCast(u7, store.data.flags.circuit) << 2);
pub fn toByte(data: TileData) u8 {
switch (data) {
.tile => |int| return 1 | (int << 1),
.flags => |flags| return (@intCast(u7, @boolToInt(flags.solid)) << 1) | (@intCast(u7, flags.circuit) << 2),
}
}
pub fn fromByte(byte: u8) TileStore {
pub fn fromByte(byte: u8) TileData {
const is_tile = (1 & byte) > 0;
if (is_tile) {
const tile = @intCast(u7, (~@as(u7, 1) & byte) >> 1);
return TileStore{
.is_tile = true,
.data = .{ .tile = tile },
};
return TileData{ .tile = tile };
} else {
const is_solid = (0b0000_0010 & byte) > 0;
const circuit = @intCast(u4, (0b0011_1100 & byte) >> 2);
return TileStore{
.is_tile = false,
.data = .{ .flags = .{
.solid = is_solid,
.circuit = circuit,
} },
};
}
}
};
pub const LevelHeader = struct {
world_x: u8,
world_y: u8,
width: u16,
size: u16,
pub fn write(header: LevelHeader, writer: anytype) !void {
try writer.writeInt(u8, header.world_x, .Big);
try writer.writeInt(u8, header.world_y, .Big);
try writer.writeInt(u16, header.width, .Big);
try writer.writeInt(u16, header.size, .Big);
}
pub fn read(reader: anytype) !LevelHeader {
return LevelHeader{
.world_x = try reader.readInt(u8, .Big),
.world_y = try reader.readInt(u8, .Big),
.width = try reader.readInt(u16, .Big),
.size = try reader.readInt(u16, .Big),
};
}
pub fn readTiles(header: LevelHeader, reader: anytype, buf: []TileStore) !void {
std.debug.assert(buf.len > header.size);
var i: usize = 0;
while (i < header.size) : (i += 1) {
buf[i] = TileStore.fromByte(try reader.readByte());
return TileData{ .flags = .{
.solid = is_solid,
.circuit = circuit,
} };
}
}
};
@ -93,16 +50,48 @@ pub const Level = struct {
world_x: u8,
world_y: u8,
width: u16,
tiles: []TileStore,
size: u16,
tiles: ?[]TileData,
pub fn init(header: LevelHeader, buf: []TileStore) Level {
pub fn init(x: u8, y: u8, width: u16, buf: []TileData) Level {
return Level{
.world_x = header.world_x,
.world_y = header.world_y,
.width = header.width,
.tiles = buf[0..header.size],
.world_x = x,
.world_y = y,
.width = width,
.size = buf.len,
.tiles = buf,
};
}
pub fn write(level: Level, writer: anytype) !void {
var tiles = level.tiles orelse return error.NullTiles;
try writer.writeInt(u8, level.world_x, .Big);
try writer.writeInt(u8, level.world_y, .Big);
try writer.writeInt(u16, level.width, .Big);
try writer.writeInt(u16, level.size, .Big);
for (tiles) |tile| {
try writer.writeByte(tile.toByte());
}
}
pub fn read(reader: anytype) !Level {
return Level{
.world_x = try reader.readInt(u8, .Big),
.world_y = try reader.readInt(u8, .Big),
.width = try reader.readInt(u16, .Big),
.size = try reader.readInt(u16, .Big),
.tiles = null,
};
}
pub fn readTiles(level: *Level, reader: anytype, buf: []TileData) !void {
std.debug.assert(buf.len >= level.size);
level.tiles = buf;
var i: usize = 0;
while (i < level.size) : (i += 1) {
buf[i] = TileData.fromByte(try reader.readByte());
}
}
};
// AutoTile algorithm datatypes

View File

@ -51,7 +51,6 @@ fn make(step: *std.build.Step) !void {
defer data.deinit();
const writer = data.writer();
// TODO: Convert LDtk data into wired format
const ldtk = try LDtk.parse(allocator, source);
defer ldtk.deinit(allocator);
@ -96,43 +95,40 @@ fn make(step: *std.build.Step) !void {
const width = @intCast(u16, circuit.__cWid);
const size = @intCast(u16, width * circuit.__cHei);
try (world.LevelHeader{
var level = world.Level{
.world_x = world_x,
.world_y = world_y,
.width = @intCast(u16, width),
.size = @intCast(u16, size),
}).write(writer);
.tiles = null,
};
level.tiles = try allocator.alloc(world.TileData, size);
defer allocator.free(level.tiles.?);
var tiles = try allocator.alloc(world.TileStore, size);
defer allocator.free(tiles);
const tiles = level.tiles.?;
for (collision.autoLayerTiles) |autotile| {
const x = @divExact(autotile.px[0], collision.__gridSize);
const y = @divExact(autotile.px[1], collision.__gridSize);
const i = @intCast(usize, x + y * width);
tiles[i] = world.TileStore{
.is_tile = true,
.data = .{ .tile = @intCast(u7, autotile.t + 1) },
};
tiles[i] = world.TileData{ .tile = @intCast(u7, autotile.t + 1) };
}
for (circuit.intGridCsv) |cir64, i| {
const cir = @intCast(u4, cir64);
const col = collision.intGridCsv[i];
if (col != 2) {
tiles[i] = world.TileStore{
.is_tile = false,
.data = .{ .flags = .{
.solid = col == 1,
.circuit = cir,
} },
};
tiles[i] = world.TileData{ .flags = .{
.solid = col == 1,
.circuit = cir,
} };
}
if (col == 2) {
tiles[i].is_tile = true;
}
try writer.writeByte(tiles[i].toByte());
// if (col == 2) {
// tiles[i].is_tile = true;
// }
}
try level.write(writer);
}
}