Write world data on build

master
Louis Pearson 2022-08-03 23:50:50 -06:00
parent 2aa246f1bd
commit f944f754b1
2 changed files with 117 additions and 43 deletions

View File

@ -1,5 +1,7 @@
//! Data types used for storing world info //! Data types used for storing world info
const std = @import("std");
// Tile Storage Types // Tile Storage Types
pub const CircuitType = enum(u4) { pub const CircuitType = enum(u4) {
None = 0, None = 0,
@ -14,17 +16,46 @@ pub const CircuitType = enum(u4) {
Source = 9, Source = 9,
}; };
pub const TileData = packed union { pub const TileData = union {
tile: u7, tile: u7,
flags: packed struct { flags: struct {
solid: bool, solid: bool,
circuit: u4, circuit: u4,
}, },
}; };
pub const TileStore = packed struct { pub const TileStore = struct {
is_tile: bool, is_tile: bool,
data: TileData, data: TileData,
pub fn toByte(store: TileStore) u8 {
if (store.is_tile) {
return 1 | (store.data.tile << 1);
} else {
return 0 | (@intCast(u2, @boolToInt(store.data.flags.solid)) << 1) | (store.data.flags.circuit << 2);
}
}
pub fn fromByte(byte: u8) TileStore {
const is_tile = (1 & byte) > 0;
if (is_tile) {
const tile = @intCast(u7, (~1 & byte) >> 1);
return TileStore{
.is_tile = is_tile,
.data = .{ .tile = tile },
};
} else {
const is_solid = (0b0000_0010 & byte) > 0;
const circuit = @intCast(u4, (0b0011_1100 & byte) >> 2);
return TileStore{
.is_tile = is_tile,
.data = .{ .flags = .{
.solid = is_solid,
.circuit = circuit,
} },
};
}
}
}; };
pub const LevelHeader = struct { pub const LevelHeader = struct {
@ -32,6 +63,30 @@ pub const LevelHeader = struct {
world_y: u8, world_y: u8,
width: u16, width: u16,
size: 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(reader.readByte());
}
}
}; };
pub const Level = struct { pub const Level = struct {

View File

@ -47,7 +47,6 @@ fn make(step: *std.build.Step) !void {
var data = std.ArrayList(u8).init(allocator); var data = std.ArrayList(u8).init(allocator);
defer data.deinit(); defer data.deinit();
const writer = data.writer(); const writer = data.writer();
_ = writer;
// TODO: Convert LDtk data into wired format // TODO: Convert LDtk data into wired format
const ldtk = try LDtk.parse(allocator, source); const ldtk = try LDtk.parse(allocator, source);
@ -56,58 +55,78 @@ fn make(step: *std.build.Step) !void {
if (ldtk.levels.len > 0) { if (ldtk.levels.len > 0) {
const level0 = ldtk.levels[0]; const level0 = ldtk.levels[0];
if (level0.layerInstances) |layers| { if (level0.layerInstances) |layers| {
var circuit: []const u8 = "null"; const world_x: u8 = @intCast(u8, @divExact(level0.worldX, (ldtk.worldGridWidth orelse 160)));
var collision: []const u8 = "null"; const world_y: u8 = @intCast(u8, @divExact(level0.worldY, (ldtk.worldGridHeight orelse 160)));
var circuit_layer: ?LDtk.LayerInstance = null;
var collision_layer: ?LDtk.LayerInstance = null;
for (layers) |layer| { for (layers) |layer| {
if (std.mem.eql(u8, layer.__identifier, "Entities")) { if (std.mem.eql(u8, layer.__identifier, "Entities")) {
std.debug.assert(layer.__type == .Entities); std.debug.assert(layer.__type == .Entities);
for (layer.entityInstances) |entity| { for (layer.entityInstances) |entity| {
std.log.warn("{s}", .{entity.__identifier}); std.log.warn("{s}", .{entity.__identifier});
} }
} } else if (std.mem.eql(u8, layer.__identifier, "Circuit")) {
else if (std.mem.eql(u8, layer.__identifier, "Circuit")) {
std.debug.assert(layer.__type == .IntGrid); std.debug.assert(layer.__type == .IntGrid);
var grid_str = try allocator.alloc(u8, @intCast(usize, layer.__cWid * layer.__cHei + layer.__cHei)); circuit_layer = layer;
defer allocator.free(grid_str); } else if (std.mem.eql(u8, layer.__identifier, "Collision")) {
var i: usize = 0;
var o: usize = 0;
for (layer.intGridCsv) |int| {
grid_str[i + o] = std.fmt.digitToChar(@intCast(u8, int), .lower);
if (grid_str[i] == '0') grid_str[i] = ' ';
i += 1;
if (@mod(i, @intCast(usize, layer.__cWid)) == 0) {
grid_str[i + o] = '\n';
o += 1;
}
}
circuit = grid_str;
}
else if (std.mem.eql(u8, layer.__identifier, "Collision")) {
std.debug.assert(layer.__type == .IntGrid); std.debug.assert(layer.__type == .IntGrid);
var grid_str = try allocator.alloc(u8, @intCast(usize, layer.__cWid * layer.__cHei + layer.__cHei)); collision_layer = layer;
var i: usize = 0;
var o: usize = 0;
for (layer.intGridCsv) |int| {
grid_str[i + o] = std.fmt.digitToChar(@intCast(u8, int), .lower);
if (grid_str[i] == '0') grid_str[i] = ' ';
i += 1;
if (@mod(i, @intCast(usize, layer.__cWid)) == 0) {
grid_str[i + o] = '\n';
o += 1;
}
}
collision = grid_str;
} else { } else {
std.log.warn("{s}: {}", .{ layer.__identifier, layer.__type }); std.log.warn("{s}: {}", .{ layer.__identifier, layer.__type });
} }
} }
std.log.warn("Circuit IntGrid:\n{s}\nCollision IntGrid:\n{s}", .{ circuit, collision});
allocator.free(circuit); if (circuit_layer == null) return error.MissingCircuitLayer;
allocator.free(collision); if (collision_layer == null) return error.MissingCollisionLayer;
std.log.warn("Layers found", .{});
const circuit = circuit_layer.?;
const collision = collision_layer.?;
std.debug.assert(circuit.__cWid == collision.__cWid);
std.debug.assert(circuit.__cHei == collision.__cHei);
const width = @intCast(u16, circuit.__cWid);
const size = @intCast(u16, width * circuit.__cHei);
try (world.LevelHeader{
.world_x = world_x,
.world_y = world_y,
.width = @intCast(u16, width),
.size = @intCast(u16, size),
}).write(writer);
var tiles = try allocator.alloc(world.TileStore, size);
defer allocator.free(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) },
};
}
for (circuit.intGridCsv) |cir64, i| {
const cir = @intCast(u4, cir64);
const col = collision.intGridCsv[i];
tiles[i] = world.TileStore{
.is_tile = false,
.data = .{
.flags = .{
.solid = col == 1,
.circuit = cir,
},
},
};
try writer.writeByte(tiles[i].toByte());
}
} }
} }