diff --git a/src/extract.zig b/src/extract.zig new file mode 100644 index 0000000..419cc7c --- /dev/null +++ b/src/extract.zig @@ -0,0 +1,92 @@ +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; + +pub const ExtractOptions = struct { + map: *Map, + circuit: *Circuit, +}; + +/// Extracts a compressed level into the map and circuit buffers +pub fn extractLevel(alloc: std.mem.Allocator, level: Level, opt: ExtractOptions) void { + const map = opt.map; + const circuit = opt.circuit; + 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 }; + + var solid_map = try alloc.alloc(bool, size); + defer alloc.free(solid_map); + + var circuit_map = try alloc.alloc(CircuitType, size); + defer alloc.free(circuit_map); + + for (level.tiles) |tile, i| { + if (tile.is_tile) { + solid_map[i] = is_solid(tile.data.tile); + map.map[i] = tile.data.tile; + circuit_map[i] = .None; + } else { + solid_map = tile.data.flags.solid; + circuit_map[i] = @intToEnum(CircuitType, tile.data.flags.circuit); + } + } + + 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 out_of_bounds = true; + var north = false; + var south = false; + var west = false; + var east = false; + + // Check horizontal neighbors + if (x == 0) { + west = out_of_bounds; + } + else if (x == width - 1) { + east = out_of_bounds; + } + else { + west = solid_map[i - 1]; + east = solid_map[i + 1]; + } + + // Check vertical neighbours + if (y == 0) { + north = out_of_bounds; + } + else if (y == height - 1) { + south = out_of_bounds; + } + else { + north = solid_map[i - width]; + south = solid_map[i + width]; + } + + autotiles[i] = AutoTile{ + .North = north, + .South = south, + .West = west, + .East = east, + }; + } + } + + for (autotiles) |autotile, i| { + map.map[i] = tileset.lookup[autotile.to_u4()]; + } +} diff --git a/src/main.zig b/src/main.zig index e32730d..81206bf 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,7 +4,7 @@ const assets = @import("assets"); const input = @import("input.zig"); const util = @import("util.zig"); -const game = @import("game.zig"); +const game = @import("rewrite.zig"); const menu = @import("menu.zig"); pub const State = enum { @@ -30,7 +30,6 @@ export fn update() void { .Game => game.update(time) catch |e| switch (e) { error.Overflow => showErr(@errorName(e)), error.OutOfBounds => showErr(@errorName(e)), - // error.IndexOutOfBounds => showErr(@errorName(e)), }, }; if (state != newState) { @@ -40,7 +39,6 @@ export fn update() void { .Game => game.start() catch |e| switch (e) { error.Overflow => showErr(@errorName(e)), error.OutOfBounds => showErr(@errorName(e)), - // error.IndexOutOfBounds => showErr(@errorName(e)), }, } } diff --git a/src/map.zig b/src/map.zig index 1076127..d1051c1 100644 --- a/src/map.zig +++ b/src/map.zig @@ -7,8 +7,6 @@ const Vec2 = util.Vec2; const Vec2f = util.Vec2f; const Cell = util.Cell; -const MAXCELLS = 400; - const width = 20; const height = 20; const tile_width = 8; diff --git a/src/menu.zig b/src/menu.zig index 70316c8..e07322b 100644 --- a/src/menu.zig +++ b/src/menu.zig @@ -36,7 +36,7 @@ pub fn update() State { switch (@intToEnum(MenuOptions, selected)) { .Continue => return .Game, .NewGame => { - _ = w4.diskw("", 0); + // _ = w4.diskw("", 0); return .Game; }, } diff --git a/src/rewrite.zig b/src/rewrite.zig new file mode 100644 index 0000000..9062679 --- /dev/null +++ b/src/rewrite.zig @@ -0,0 +1,54 @@ +const world_data = @import("world_data"); +const Circuit = @import("map.zig"); +const input = @import("input.zig"); +const Map = @import("map.zig"); +const State = @import("main.zig").State; +const std = @import("std"); +const w4 = @import("wasm4.zig"); +const world = @import("world.zig"); + +const Vec2 = w4.Vec2; + +var frame_fba_buf: [4096]u8 = undefined; +var frame_fba = std.heap.FixedBufferAllocator.init(&frame_fba_buf); +var frame_alloc = frame_fba.allocator(); + +var map_buf: [400]u8 = undefined; +var map: Map = undefined; + +var circuit_lvl_buf: [400]u8 = undefined; +var circuit_buf : [400]u8 = undefined; +var circuit: Circuit = undefined; + +var level_size = Vec2{20, 20}; + +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{ + .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); +} + +pub fn update() State { + // Reset the frame allocator + frame_fba.reset(); + + w4.DRAW_COLORS.* = 0x0004; + w4.rect(Vec2{ 0, 0 }, Vec2{ 160, 160 }); + w4.DRAW_COLORS.* = 0x0001; + + const camera = Vec2{0, 0}; + + map.draw(camera); + circuit.draw(camera); + + return .Game; +} diff --git a/src/world.zig b/src/world.zig index 50d7813..24cacd2 100644 --- a/src/world.zig +++ b/src/world.zig @@ -1,68 +1,62 @@ -const TileValue = union(enum) { - Tile, - Size, +//! Data types used for storing world info + +// Tile Storage Types +pub const CircuitType = enum(u4) { + None = 0, + Conduit = 1, + Plug = 2, + Switch_Off = 3, + Switch_On = 4, + Join = 5, + And = 6, + Xor = 7, + Outlet = 8, + Source = 9, }; -// 2 Modes -// Tile: -// 0b0TTT_TTTT -// 2 layer: -// 0b1XXS_CCCC -// T = Tile number, 0-127 -// X = Reserved -// S = Solid -// C = Circuit +pub const TileData = packed union { + tile: u7, + flags: packed struct { + solid: bool, + circuit: u4, + }, +}; -/// 0bDCBA -/// +---+---+ -/// | A | B | -/// +---+---+ -/// | C | D | -/// +---+---+ -/// NE 0b0001 -/// NW 0b0010 -/// SW 0b0100 -/// SE 0b1000 -/// 0 - -const AutoTileRule = struct { - A: u8, - B: u8, +pub const TileStore = packed struct { + is_tile: bool, + data: TileData, +}; + +pub const LevelHeader = struct { + world_x: u8, + world_y: u8, + width: u16, + size: u16, +}; + +pub const Level = struct { + world_x: u8, + world_y: u8, + width: u16, + tiles: []TileStore, +}; + +// AutoTile algorithm datatypes +pub const AutoTile = packed struct { + North: bool, + West: bool, + South: bool, + East: bool, + + pub fn to_u4(autotile: AutoTile) u4 { + return @bitCast(u4, autotile); + } + + pub fn from_u4(int: u4) AutoTile { + return @bitCast(AutoTile, int); + } +}; + +pub const AutoTileset = struct { lookup: [16]u8, }; - -/// Reference enum mapping numbers to names -/// X = Exclude (only one side present) -/// N = North -/// W = West -/// E = East -/// S = South -/// H = Horizontal -/// V = Vertical -pub const Side = enum(u4) { - X_ALL = 0, - N = 1, - W = 2, - NW = 3, - E = 4, - NE = 5, - H_BEAM = 6, - X_S = 7, - S = 8, - V_BEAM = 9, - SW = 10, - X_E = 11, - SE = 12, - X_W = 13, - X_N = 14, - ALL = 15, -}; - -const AutoTiling = struct { - /// Bitmask to tile mapping - const AutoTileLookup = [16]u8; - - tables: []AutoTileLookup, - /// Use value A for out of bounds - outOfBounds: u8, - values: []u8, -}; diff --git a/tools/LDtkImport.zig b/tools/LDtkImport.zig index 335ade9..7d03788 100644 --- a/tools/LDtkImport.zig +++ b/tools/LDtkImport.zig @@ -1,6 +1,7 @@ //! Uses zig-ldtk to convert a ldtk file into a binary format for wired const std = @import("std"); const LDtk = @import("../deps/zig-ldtk/src/LDtk.zig"); +const world = @import("../src/world.zig"); const KB = 1024; const MB = 1024 * KB;