Succesfully load autotiles

master
Louis Pearson 2022-08-04 01:59:32 -06:00
parent f944f754b1
commit 21f8ae7087
6 changed files with 114 additions and 40 deletions

View File

@ -12,9 +12,13 @@ pub fn build(b: *std.build.Builder) !void {
.output_name = "mapldtk",
});
const data_step = b.addOptions();
data_step.addOptionFileSource("path", .{.generated = &ldtk.world_data });
const mode = b.standardReleaseOptions();
const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned);
lib.step.dependOn(&ldtk.step);
lib.step.dependOn(&data_step.step);
lib.addPackage(data_step.getPackage("world_data"));
lib.addPackage(assets);
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });

View File

@ -1,23 +1,37 @@
const w4 = @import("wasm4.zig");
const std = @import("std");
const Map = @import("map.zig");
const Circuit = @import("circuit.zig");
const world = @import("world.zig");
const Level = world.Level;
const Level = world.AutoTile;
const AutoTile = world.AutoTile;
const CircuitType = world.CircuitType;
pub const ExtractOptions = struct {
pub const Options = struct {
map: *Map,
circuit: *Circuit,
alloc: std.mem.Allocator,
level: world.Level,
tileset: world.AutoTileset,
};
fn is_solid(tile: u7) bool {
return tile != 0 and tile != 1;
}
/// Extracts a compressed level into the map and circuit buffers
pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions) void {
pub fn extractLevel(opt: Options) !void {
const map = opt.map;
const circuit = opt.circuit;
const alloc = opt.alloc;
const level = opt.level;
const tileset = opt.tileset;
const width = level.width;
const height = @divExact(@intCast(u16, level.tiles.len), level.width);
const size = level.tiles.len;
map.map_size = .{ level.width, height };
circuit.map_size = .{ level.width, height };
@ -29,23 +43,29 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
for (level.tiles) |tile, i| {
if (tile.is_tile) {
solid_map[i] = is_solid(tile.data.tile);
map.map[i] = tile.data.tile;
// solid_map[i] = is_solid(tile.data.tile);
map.tiles[i] = tile.data.tile;
circuit_map[i] = .None;
} else {
solid_map = tile.data.flags.solid;
solid_map[i] = tile.data.flags.solid;
circuit_map[i] = @intToEnum(CircuitType, tile.data.flags.circuit);
}
}
var autotiles = try alloc.alloc(AutoTile, size);
var autotiles = try alloc.alloc(?AutoTile, size);
defer alloc.free(autotiles);
{
var i: usize = 0;
while (i < level.tiles.len) : (i += 1) {
const x = @mod(i, width);
const y = @divTrunc(a, width);
const y = @divTrunc(i, width);
const stride = width;
if (!solid_map[i]) {
autotiles[i] = null;
continue;
}
const out_of_bounds = true;
var north = false;
@ -56,11 +76,11 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
// Check horizontal neighbors
if (x == 0) {
west = out_of_bounds;
}
else if (x == width - 1) {
east = solid_map[i + 1];
} else if (x == width - 1) {
west = solid_map[i - 1];
east = out_of_bounds;
}
else {
} else {
west = solid_map[i - 1];
east = solid_map[i + 1];
}
@ -68,13 +88,13 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
// Check vertical neighbours
if (y == 0) {
north = out_of_bounds;
}
else if (y == height - 1) {
south = solid_map[i + stride];
} else if (y == height - 1) {
north = solid_map[i - stride];
south = out_of_bounds;
}
else {
north = solid_map[i - width];
south = solid_map[i + width];
} else {
north = solid_map[i - stride];
south = solid_map[i + stride];
}
autotiles[i] = AutoTile{
@ -86,7 +106,11 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
}
}
for (autotiles) |autotile, i| {
map.map[i] = tileset.lookup[autotile.to_u4()];
for (autotiles) |autotile_opt, i| {
if (autotile_opt) |autotile| {
const li = autotile.to_u4();
const tile = tileset.lookup[li];
map.tiles[i] = tile;
}
}
}

View File

@ -29,7 +29,8 @@ export fn update() void {
.Menu => menu.update(),
.Game => game.update(time) catch |e| switch (e) {
error.Overflow => showErr(@errorName(e)),
error.OutOfBounds => showErr(@errorName(e)),
// error.OutOfBounds => showErr(@errorName(e)),
error.EndOfStream => showErr(@errorName(e)),
},
};
if (state != newState) {
@ -38,7 +39,9 @@ export fn update() void {
.Menu => menu.start(),
.Game => game.start() catch |e| switch (e) {
error.Overflow => showErr(@errorName(e)),
error.OutOfBounds => showErr(@errorName(e)),
// error.OutOfBounds => showErr(@errorName(e)),
error.EndOfStream => showErr(@errorName(e)),
error.OutOfMemory => showErr(@errorName(e)),
},
}
}

View File

@ -1,5 +1,6 @@
const world_data = @import("world_data");
const Circuit = @import("map.zig");
const extract = @import("extract.zig");
const world_data = @embedFile(@import("world_data").path);
const Circuit = @import("circuit.zig");
const input = @import("input.zig");
const Map = @import("map.zig");
const State = @import("main.zig").State;
@ -22,22 +23,50 @@ var circuit: Circuit = undefined;
var level_size = Vec2{ 20, 20 };
pub fn start() void {
pub fn start() !void {
circuit = try Circuit.init(&circuit_buf, &circuit_lvl_buf, level_size);
map = Map.init(&map_buf, level_size);
const extract_opt = world.ExtractOptions{
var stream = std.io.FixedBufferStream([]const u8){
.pos = 0,
.buffer = world_data,
};
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);
try extract.extractLevel(.{
.alloc = frame_alloc,
.level = level,
.map = &map,
.circuit = &circuit,
};
const world_reader = std.io.FixedBufferStream([]const u8).reader();
const level = world_reader.readStruct(world.Level);
world.extractLevel(frame_alloc, level, extract_opt);
.tileset = world.AutoTileset{ .lookup = .{
35, // Island
51, // North
52, // West
55, // West-North
50, // East
53, // East-North
19, // East-West
54, // East-West-North
49, // South
20, // South-North
23, // South-West
39, // South-West-North
21, // South-East
37, // South-East-North
22, // South-East-West
0, // South-East-West-North
}},
});
}
pub fn update() State {
pub fn update(time: usize) !State {
_ = time;
// Reset the frame allocator
frame_fba.reset();

View File

@ -39,7 +39,7 @@ pub const TileStore = struct {
pub fn fromByte(byte: u8) TileStore {
const is_tile = (1 & byte) > 0;
if (is_tile) {
const tile = @intCast(u7, (~1 & byte) >> 1);
const tile = @intCast(u7, (~@as(u7, 1) & byte) >> 1);
return TileStore{
.is_tile = is_tile,
.data = .{ .tile = tile },
@ -84,7 +84,7 @@ pub const LevelHeader = struct {
std.debug.assert(buf.len > header.size);
var i: usize = 0;
while (i < header.size) : (i += 1) {
buf[i] = TileStore.fromByte(reader.readByte());
buf[i] = TileStore.fromByte(try reader.readByte());
}
}
};
@ -94,14 +94,23 @@ pub const Level = struct {
world_y: u8,
width: u16,
tiles: []TileStore,
pub fn init(header: LevelHeader, buf: []TileStore) Level {
return Level {
.world_x = header.world_x,
.world_y = header.world_y,
.width = header.width,
.tiles = buf[0..header.size],
};
}
};
// AutoTile algorithm datatypes
pub const AutoTile = packed struct {
North: bool,
West: bool,
South: bool,
East: bool,
South: bool,
pub fn to_u4(autotile: AutoTile) u4 {
return @bitCast(u4, autotile);

View File

@ -12,6 +12,7 @@ step: std.build.Step,
builder: *std.build.Builder,
source_path: std.build.FileSource,
output_name: []const u8,
world_data: std.build.GeneratedFile,
pub fn create(b: *std.build.Builder, opt: struct {
source_path: std.build.FileSource,
@ -23,7 +24,9 @@ pub fn create(b: *std.build.Builder, opt: struct {
.builder = b,
.source_path = opt.source_path,
.output_name = opt.output_name,
.world_data = undefined,
};
result.*.world_data = std.build.GeneratedFile{ .step = &result.*.step };
return result;
}
@ -136,4 +139,6 @@ fn make(step: *std.build.Step) !void {
else => return e,
};
try cwd.writeFile(output, data.items);
this.world_data.path = output;
}