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 level = opt.level;
const tileset = opt.tileset; const tileset = opt.tileset;
const tiles = level.tiles orelse return error.NullTiles;
const width = level.width; const width = level.width;
const height = @divExact(@intCast(u16, level.tiles.len), level.width); const height = @divExact(@intCast(u16, tiles.len), level.width);
const size = level.tiles.len; const size = tiles.len;
map.map_size = .{ level.width, height }; map.map_size = .{ level.width, height };
circuit.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); var circuit_map = try alloc.alloc(CircuitType, size);
defer alloc.free(circuit_map); defer alloc.free(circuit_map);
for (level.tiles) |tile, i| { for (tiles) |data, i| {
if (tile.is_tile) { switch (data) {
auto_map[i] = false; .tile => |tile| {
map.tiles[i] = tile.data.tile; auto_map[i] = false;
circuit_map[i] = .None; map.tiles[i] = tile;
} else { circuit_map[i] = .None;
auto_map[i] = tile.data.flags.solid; },
circuit_map[i] = @intToEnum(CircuitType, tile.data.flags.circuit); .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.OutOfBounds => showErr(@errorName(e)),
error.EndOfStream => showErr(@errorName(e)), error.EndOfStream => showErr(@errorName(e)),
error.OutOfMemory => 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; 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 fba = std.heap.FixedBufferAllocator.init(&fba_buf);
var alloc = fba.allocator(); var alloc = fba.allocator();
@ -49,11 +49,9 @@ pub fn start() !void {
}; };
const world_reader = stream.reader(); const world_reader = stream.reader();
const header = try world.LevelHeader.read(world_reader); var level = try world.Level.read(world_reader);
var tile_buf: [4096]world.TileStore = undefined; var level_buf = try alloc.alloc(world.TileData, level.size);
try header.readTiles(world_reader, &tile_buf); try level.readTiles(world_reader, level_buf);
const level = world.Level.init(header, &tile_buf);
try extract.extractLevel(.{ try extract.extractLevel(.{
.alloc = frame_alloc, .alloc = frame_alloc,

View File

@ -16,75 +16,32 @@ pub const CircuitType = enum(u4) {
Source = 9, Source = 9,
}; };
pub const TileData = union { pub const TileData = union(enum) {
tile: u7, tile: u7,
flags: struct { flags: struct {
solid: bool, solid: bool,
circuit: u4, circuit: u4,
}, },
};
pub const TileStore = struct { pub fn toByte(data: TileData) u8 {
is_tile: bool, switch (data) {
data: TileData, .tile => |int| return 1 | (int << 1),
.flags => |flags| return (@intCast(u7, @boolToInt(flags.solid)) << 1) | (@intCast(u7, flags.circuit) << 2),
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 fromByte(byte: u8) TileStore { pub fn fromByte(byte: u8) TileData {
const is_tile = (1 & byte) > 0; const is_tile = (1 & byte) > 0;
if (is_tile) { if (is_tile) {
const tile = @intCast(u7, (~@as(u7, 1) & byte) >> 1); const tile = @intCast(u7, (~@as(u7, 1) & byte) >> 1);
return TileStore{ return TileData{ .tile = tile };
.is_tile = true,
.data = .{ .tile = tile },
};
} else { } else {
const is_solid = (0b0000_0010 & byte) > 0; const is_solid = (0b0000_0010 & byte) > 0;
const circuit = @intCast(u4, (0b0011_1100 & byte) >> 2); const circuit = @intCast(u4, (0b0011_1100 & byte) >> 2);
return TileStore{ return TileData{ .flags = .{
.is_tile = false, .solid = is_solid,
.data = .{ .flags = .{ .circuit = circuit,
.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());
} }
} }
}; };
@ -93,16 +50,48 @@ pub const Level = struct {
world_x: u8, world_x: u8,
world_y: u8, world_y: u8,
width: u16, 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{ return Level{
.world_x = header.world_x, .world_x = x,
.world_y = header.world_y, .world_y = y,
.width = header.width, .width = width,
.tiles = buf[0..header.size], .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 // AutoTile algorithm datatypes

View File

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