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", .output_name = "mapldtk",
}); });
const data_step = b.addOptions();
data_step.addOptionFileSource("path", .{.generated = &ldtk.world_data });
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned); 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.addPackage(assets);
lib.setBuildMode(mode); lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });

View File

@ -1,23 +1,37 @@
const w4 = @import("wasm4.zig");
const std = @import("std"); const std = @import("std");
const Map = @import("map.zig"); const Map = @import("map.zig");
const Circuit = @import("circuit.zig"); const Circuit = @import("circuit.zig");
const world = @import("world.zig"); const world = @import("world.zig");
const Level = world.Level; 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, map: *Map,
circuit: *Circuit, 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 /// 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 map = opt.map;
const circuit = opt.circuit; const circuit = opt.circuit;
const alloc = opt.alloc;
const level = opt.level;
const tileset = opt.tileset;
const width = level.width; const width = level.width;
const height = @divExact(@intCast(u16, level.tiles.len), level.width); const height = @divExact(@intCast(u16, level.tiles.len), level.width);
const size = level.tiles.len; const size = level.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 };
@ -29,23 +43,29 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
for (level.tiles) |tile, i| { for (level.tiles) |tile, i| {
if (tile.is_tile) { if (tile.is_tile) {
solid_map[i] = is_solid(tile.data.tile); // solid_map[i] = is_solid(tile.data.tile);
map.map[i] = tile.data.tile; map.tiles[i] = tile.data.tile;
circuit_map[i] = .None; circuit_map[i] = .None;
} else { } else {
solid_map = tile.data.flags.solid; solid_map[i] = tile.data.flags.solid;
circuit_map[i] = @intToEnum(CircuitType, tile.data.flags.circuit); 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); defer alloc.free(autotiles);
{ {
var i: usize = 0; var i: usize = 0;
while (i < level.tiles.len) : (i += 1) { while (i < level.tiles.len) : (i += 1) {
const x = @mod(i, width); 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; const out_of_bounds = true;
var north = false; var north = false;
@ -56,11 +76,11 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
// Check horizontal neighbors // Check horizontal neighbors
if (x == 0) { if (x == 0) {
west = out_of_bounds; west = out_of_bounds;
} east = solid_map[i + 1];
else if (x == width - 1) { } else if (x == width - 1) {
west = solid_map[i - 1];
east = out_of_bounds; east = out_of_bounds;
} } else {
else {
west = solid_map[i - 1]; west = solid_map[i - 1];
east = 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 // Check vertical neighbours
if (y == 0) { if (y == 0) {
north = out_of_bounds; north = out_of_bounds;
} south = solid_map[i + stride];
else if (y == height - 1) { } else if (y == height - 1) {
north = solid_map[i - stride];
south = out_of_bounds; south = out_of_bounds;
} } else {
else { north = solid_map[i - stride];
north = solid_map[i - width]; south = solid_map[i + stride];
south = solid_map[i + width];
} }
autotiles[i] = AutoTile{ autotiles[i] = AutoTile{
@ -86,7 +106,11 @@ pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions)
} }
} }
for (autotiles) |autotile, i| { for (autotiles) |autotile_opt, i| {
map.map[i] = tileset.lookup[autotile.to_u4()]; 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(), .Menu => menu.update(),
.Game => game.update(time) catch |e| switch (e) { .Game => game.update(time) catch |e| switch (e) {
error.Overflow => showErr(@errorName(e)), error.Overflow => showErr(@errorName(e)),
error.OutOfBounds => showErr(@errorName(e)), // error.OutOfBounds => showErr(@errorName(e)),
error.EndOfStream => showErr(@errorName(e)),
}, },
}; };
if (state != newState) { if (state != newState) {
@ -38,7 +39,9 @@ export fn update() void {
.Menu => menu.start(), .Menu => menu.start(),
.Game => game.start() catch |e| switch (e) { .Game => game.start() catch |e| switch (e) {
error.Overflow => showErr(@errorName(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 extract = @import("extract.zig");
const Circuit = @import("map.zig"); const world_data = @embedFile(@import("world_data").path);
const Circuit = @import("circuit.zig");
const input = @import("input.zig"); const input = @import("input.zig");
const Map = @import("map.zig"); const Map = @import("map.zig");
const State = @import("main.zig").State; const State = @import("main.zig").State;
@ -17,27 +18,55 @@ var map_buf: [400]u8 = undefined;
var map: Map = undefined; var map: Map = undefined;
var circuit_lvl_buf: [400]u8 = undefined; var circuit_lvl_buf: [400]u8 = undefined;
var circuit_buf : [400]u8 = undefined; var circuit_buf: [400]u8 = undefined;
var circuit: Circuit = undefined; var circuit: Circuit = undefined;
var level_size = Vec2{20, 20}; 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); circuit = try Circuit.init(&circuit_buf, &circuit_lvl_buf, level_size);
map = Map.init(&map_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, .map = &map,
.circuit = &circuit, .circuit = &circuit,
}; .tileset = world.AutoTileset{ .lookup = .{
35, // Island
const world_reader = std.io.FixedBufferStream([]const u8).reader(); 51, // North
const level = world_reader.readStruct(world.Level); 52, // West
55, // West-North
world.extractLevel(frame_alloc, level, extract_opt); 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 // Reset the frame allocator
frame_fba.reset(); frame_fba.reset();
@ -45,7 +74,7 @@ pub fn update() State {
w4.rect(Vec2{ 0, 0 }, Vec2{ 160, 160 }); w4.rect(Vec2{ 0, 0 }, Vec2{ 160, 160 });
w4.DRAW_COLORS.* = 0x0001; w4.DRAW_COLORS.* = 0x0001;
const camera = Vec2{0, 0}; const camera = Vec2{ 0, 0 };
map.draw(camera); map.draw(camera);
circuit.draw(camera); circuit.draw(camera);

View File

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

View File

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