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
const std = @import("std");
// Tile Storage Types
pub const CircuitType = enum(u4) {
None = 0,
@ -14,24 +16,77 @@ pub const CircuitType = enum(u4) {
Source = 9,
};
pub const TileData = packed union {
pub const TileData = union {
tile: u7,
flags: packed struct {
flags: struct {
solid: bool,
circuit: u4,
},
};
pub const TileStore = packed struct {
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 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 {
world_x: u8,
world_y: u8,
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 {

View File

@ -47,7 +47,6 @@ fn make(step: *std.build.Step) !void {
var data = std.ArrayList(u8).init(allocator);
defer data.deinit();
const writer = data.writer();
_ = writer;
// TODO: Convert LDtk data into wired format
const ldtk = try LDtk.parse(allocator, source);
@ -56,58 +55,78 @@ fn make(step: *std.build.Step) !void {
if (ldtk.levels.len > 0) {
const level0 = ldtk.levels[0];
if (level0.layerInstances) |layers| {
var circuit: []const u8 = "null";
var collision: []const u8 = "null";
const world_x: u8 = @intCast(u8, @divExact(level0.worldX, (ldtk.worldGridWidth orelse 160)));
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| {
if (std.mem.eql(u8, layer.__identifier, "Entities")) {
std.debug.assert(layer.__type == .Entities);
for (layer.entityInstances) |entity| {
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);
var grid_str = try allocator.alloc(u8, @intCast(usize, layer.__cWid * layer.__cHei + layer.__cHei));
defer allocator.free(grid_str);
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")) {
circuit_layer = layer;
} else if (std.mem.eql(u8, layer.__identifier, "Collision")) {
std.debug.assert(layer.__type == .IntGrid);
var grid_str = try allocator.alloc(u8, @intCast(usize, layer.__cWid * layer.__cHei + layer.__cHei));
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;
collision_layer = layer;
} else {
std.log.warn("{s}: {}", .{ layer.__identifier, layer.__type });
}
}
std.log.warn("Circuit IntGrid:\n{s}\nCollision IntGrid:\n{s}", .{ circuit, collision});
allocator.free(circuit);
allocator.free(collision);
if (circuit_layer == null) return error.MissingCircuitLayer;
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());
}
}
}