Remove bounded array
parent
d27051e526
commit
8c7a6b096f
|
@ -190,27 +190,36 @@ const MAXLOGIC = 40;
|
||||||
|
|
||||||
pub const CellData = struct { level: u8 = 0, tile: u8 };
|
pub const CellData = struct { level: u8 = 0, tile: u8 };
|
||||||
|
|
||||||
const BridgeState = struct { cells: [2]Cell, id: usize, enabled: bool };
|
pub const BridgeState = struct { cells: [2]Cell, id: usize, enabled: bool };
|
||||||
const DoorState = struct { cell: Cell, enabled: bool };
|
pub const DoorState = struct { cell: Cell, enabled: bool };
|
||||||
|
|
||||||
/// Tile id of the tiles
|
/// Tile id of the tiles
|
||||||
map: []u8,
|
map: []u8,
|
||||||
/// Logic levels of the tiles
|
/// Logic levels of the tiles
|
||||||
levels: []u8,
|
levels: []u8,
|
||||||
map_size: Vec2,
|
map_size: Vec2,
|
||||||
bridges: std.BoundedArray(BridgeState, MAXBRIDGES),
|
bridges: util.Buffer(BridgeState),
|
||||||
sources: std.BoundedArray(Cell, MAXSOURCES),
|
sources: util.Buffer(Cell),
|
||||||
doors: std.BoundedArray(DoorState, MAXDOORS),
|
doors: util.Buffer(DoorState),
|
||||||
|
|
||||||
pub fn init(map: []u8, levels: []u8, map_size: Vec2) !@This() {
|
pub const Options = struct {
|
||||||
std.debug.assert(map.len == levels.len);
|
map: []u8,
|
||||||
|
levels: []u8,
|
||||||
|
map_size: Vec2,
|
||||||
|
bridges: []BridgeState,
|
||||||
|
sources: []Cell,
|
||||||
|
doors: []DoorState,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(opt: Options) @This() {
|
||||||
|
std.debug.assert(opt.map.len == opt.levels.len);
|
||||||
var this = @This(){
|
var this = @This(){
|
||||||
.map = map,
|
.map = opt.map,
|
||||||
.levels = levels,
|
.levels = opt.levels,
|
||||||
.map_size = map_size,
|
.map_size = opt.map_size,
|
||||||
.bridges = try std.BoundedArray(BridgeState, MAXBRIDGES).init(0),
|
.bridges = util.Buffer(BridgeState).init(opt.bridges),
|
||||||
.sources = try std.BoundedArray(Cell, MAXSOURCES).init(0),
|
.sources = util.Buffer(Cell).init(opt.sources),
|
||||||
.doors = try std.BoundedArray(DoorState, MAXDOORS).init(0),
|
.doors = util.Buffer(DoorState).init(opt.doors),
|
||||||
};
|
};
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -245,20 +254,22 @@ pub fn addDoor(this: *@This(), cell: Cell) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enabledBridges(this: @This()) !std.BoundedArray(usize, MAXBRIDGES) {
|
pub fn enabledBridges(this: @This(), alloc: std.mem.Allocator) !util.Buffer(usize) {
|
||||||
var items = try std.BoundedArray(usize, MAXBRIDGES).init(0);
|
var items = try alloc.alloc(usize, this.bridges.len);
|
||||||
for (this.bridges.constSlice()) |b| {
|
var buffer = util.Buffer(usize).init(items);
|
||||||
if (b.enabled) try items.append(b.id);
|
for (this.bridges.items) |b| {
|
||||||
|
if (b.enabled) buffer.append(b.id);
|
||||||
}
|
}
|
||||||
return items;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enabledDoors(this: @This()) !std.BoundedArray(Cell, MAXDOORS) {
|
pub fn enabledDoors(this: @This(), alloc: std.mem.Allocator) !util.Buffer(Cell) {
|
||||||
var items = try std.BoundedArray(Cell, MAXDOORS).init(0);
|
var items = try alloc.alloc(Cell, this.doors.len);
|
||||||
for (this.doors.constSlice()) |d| {
|
var buffer = util.buffer(Cell).init(items);
|
||||||
if (d.enabled) try items.append(d.cell);
|
for (this.doors.items) |d| {
|
||||||
|
if (d.enabled) buffer.append(d.cell);
|
||||||
}
|
}
|
||||||
return items;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isEnabled(this: @This(), cell: Cell) bool {
|
pub fn isEnabled(this: @This(), cell: Cell) bool {
|
||||||
|
@ -294,9 +305,14 @@ pub fn reset(this: *@This()) void {
|
||||||
const w4 = @import("wasm4.zig");
|
const w4 = @import("wasm4.zig");
|
||||||
const Queue = util.Queue(Cell, MAXCELLS);
|
const Queue = util.Queue(Cell, MAXCELLS);
|
||||||
// Returns number of cells filled
|
// Returns number of cells filled
|
||||||
pub fn fill(this: *@This()) !usize {
|
pub fn fill(this: *@This(), alloc: std.mem.Allocator) !usize {
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
var visited = try std.BoundedArray(usize, MAXCELLS).init(0);
|
|
||||||
|
var items = try alloc.alloc(usize, MAXCELLS);
|
||||||
|
defer alloc.free(items);
|
||||||
|
|
||||||
|
var visited = util.Buffer(usize).init(items);
|
||||||
|
|
||||||
var q = try Queue.init();
|
var q = try Queue.init();
|
||||||
for (this.sources.slice()) |source| {
|
for (this.sources.slice()) |source| {
|
||||||
try q.insert(source);
|
try q.insert(source);
|
||||||
|
|
|
@ -38,7 +38,7 @@ export fn update() void {
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
.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.EndOfStream => showErr(@errorName(e)),
|
||||||
error.OutOfMemory => showErr(@errorName(e)),
|
error.OutOfMemory => showErr(@errorName(e)),
|
||||||
|
|
24
src/map.zig
24
src/map.zig
|
@ -107,17 +107,35 @@ fn getTile(this: @This(), x: i32, y: i32) ?u8 {
|
||||||
return this.tiles[@intCast(u32, i)];
|
return this.tiles[@intCast(u32, i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collide(this: @This(), rect: util.AABB) !std.BoundedArray(util.AABB, 9) {
|
pub const CollisionInfo = struct {
|
||||||
|
len: usize,
|
||||||
|
items: [9]util.AABB,
|
||||||
|
|
||||||
|
pub fn init() CollisionInfo {
|
||||||
|
return CollisionInfo {
|
||||||
|
.len = 0,
|
||||||
|
.items = undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(col: CollisionInfo, item: util.AABB) void {
|
||||||
|
std.debug.assert(col.len < 9);
|
||||||
|
col.items[col.len] = item;
|
||||||
|
col.len += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn collide(this: @This(), rect: util.AABB) CollisionInfo {
|
||||||
const top_left = rect.pos / tile_sizef;
|
const top_left = rect.pos / tile_sizef;
|
||||||
const bot_right = (rect.pos + rect.size) / tile_sizef;
|
const bot_right = (rect.pos + rect.size) / tile_sizef;
|
||||||
var collisions = try std.BoundedArray(util.AABB, 9).init(0);
|
var collisions = CollisionInfo.init();
|
||||||
|
|
||||||
var i: isize = @floatToInt(i32, top_left[0]);
|
var i: isize = @floatToInt(i32, top_left[0]);
|
||||||
while (i <= @floatToInt(i32, bot_right[0])) : (i += 1) {
|
while (i <= @floatToInt(i32, bot_right[0])) : (i += 1) {
|
||||||
var a: isize = @floatToInt(i32, top_left[1]);
|
var a: isize = @floatToInt(i32, top_left[1]);
|
||||||
while (a <= @floatToInt(i32, bot_right[1])) : (a += 1) {
|
while (a <= @floatToInt(i32, bot_right[1])) : (a += 1) {
|
||||||
if (this.isSolid(Cell{ i, a })) {
|
if (this.isSolid(Cell{ i, a })) {
|
||||||
try collisions.append(util.AABB{
|
collisions.append(util.AABB{
|
||||||
.pos = Vec2f{
|
.pos = Vec2f{
|
||||||
@intToFloat(f32, i * tile_width),
|
@intToFloat(f32, i * tile_width),
|
||||||
@intToFloat(f32, a * tile_height),
|
@intToFloat(f32, a * tile_height),
|
||||||
|
|
|
@ -30,8 +30,6 @@ pub const Sfx = struct {
|
||||||
flags: w4.ToneFlags,
|
flags: w4.ToneFlags,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MusicCommand = std.BoundedArray(Sfx, 4);
|
|
||||||
|
|
||||||
pub const Intensity = enum(u8) {
|
pub const Intensity = enum(u8) {
|
||||||
calm = 0,
|
calm = 0,
|
||||||
active = 1,
|
active = 1,
|
||||||
|
@ -91,8 +89,9 @@ pub const Procedural = struct {
|
||||||
this.collect = .{ .score = score, .start = beatTotal + 1, .end = beatTotal + (this.beatsPerBar * length) + 1 };
|
this.collect = .{ .score = score, .start = beatTotal + 1, .end = beatTotal + (this.beatsPerBar * length) + 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNext(this: *@This(), dt: u32) !MusicCommand {
|
pub fn getNext(this: *@This(), dt: u32) MusicCommand {
|
||||||
var cmd = try MusicCommand.init(0);
|
var i = 0;
|
||||||
|
var cmd: [4]Sfx = undefined;
|
||||||
const beatProgress = this.tick % this.beat;
|
const beatProgress = this.tick % this.beat;
|
||||||
const beatTotal = @divTrunc(this.tick, this.beat);
|
const beatTotal = @divTrunc(this.tick, this.beat);
|
||||||
const beat = beatTotal % this.beatsPerBar;
|
const beat = beatTotal % this.beatsPerBar;
|
||||||
|
@ -103,12 +102,13 @@ pub const Procedural = struct {
|
||||||
const playNote = if (collect.score < 6) beat % 2 == 0 else beat % 4 != 3;
|
const playNote = if (collect.score < 6) beat % 2 == 0 else beat % 4 != 3;
|
||||||
if (beatTotal >= collect.start and beatTotal < collect.end and playNote and beatProgress == 0) {
|
if (beatTotal >= collect.start and beatTotal < collect.end and playNote and beatProgress == 0) {
|
||||||
// const notelen = @intCast(u8, this.beat * this.beatsPerBar);
|
// const notelen = @intCast(u8, this.beat * this.beatsPerBar);
|
||||||
try cmd.append(Sfx{
|
cmd[i] = (Sfx{
|
||||||
.freq = .{ .start = this.nextNote(this.note) },
|
.freq = .{ .start = this.nextNote(this.note) },
|
||||||
.duration = .{ .sustain = 5, .release = 5 },
|
.duration = .{ .sustain = 5, .release = 5 },
|
||||||
.volume = 25,
|
.volume = 25,
|
||||||
.flags = .{ .channel = .pulse2, .mode = .p25 },
|
.flags = .{ .channel = .pulse2, .mode = .p25 },
|
||||||
});
|
});
|
||||||
|
i += 1;
|
||||||
this.note += 1;
|
this.note += 1;
|
||||||
}
|
}
|
||||||
if (bar > collect.end) {
|
if (bar > collect.end) {
|
||||||
|
@ -116,24 +116,33 @@ pub const Procedural = struct {
|
||||||
this.collect = null;
|
this.collect = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.intensity.atLeast(.calm) and beat == 0 and beatProgress == 0) try cmd.append(.{
|
if (this.intensity.atLeast(.calm) and beat == 0 and beatProgress == 0) {
|
||||||
|
cmd[i] = (.{
|
||||||
.freq = .{ .start = 220, .end = 110 },
|
.freq = .{ .start = 220, .end = 110 },
|
||||||
.duration = .{ .release = 3 },
|
.duration = .{ .release = 3 },
|
||||||
.volume = 100,
|
.volume = 100,
|
||||||
.flags = .{ .channel = .triangle },
|
.flags = .{ .channel = .triangle },
|
||||||
});
|
});
|
||||||
if (this.intensity.atLeast(.active) and beat == this.beatsPerBar / 2 and beatProgress == 0) try cmd.append(.{
|
i += 1;
|
||||||
|
}
|
||||||
|
if (this.intensity.atLeast(.active) and beat == this.beatsPerBar / 2 and beatProgress == 0) {
|
||||||
|
cmd[i] = (.{
|
||||||
.freq = .{ .start = 110, .end = 55 },
|
.freq = .{ .start = 110, .end = 55 },
|
||||||
.duration = .{ .release = 3 },
|
.duration = .{ .release = 3 },
|
||||||
.volume = 100,
|
.volume = 100,
|
||||||
.flags = .{ .channel = .triangle },
|
.flags = .{ .channel = .triangle },
|
||||||
});
|
});
|
||||||
if (this.walking and beat % 3 == 1 and beatProgress == 7) try cmd.append(.{
|
i += 1;
|
||||||
|
}
|
||||||
|
if (this.walking and beat % 3 == 1 and beatProgress == 7) {
|
||||||
|
cmd[i] = (.{
|
||||||
.freq = .{ .start = 1761, .end = 1 },
|
.freq = .{ .start = 1761, .end = 1 },
|
||||||
.duration = .{ .release = 5 },
|
.duration = .{ .release = 5 },
|
||||||
.volume = 25,
|
.volume = 25,
|
||||||
.flags = .{ .channel = .noise },
|
.flags = .{ .channel = .noise },
|
||||||
});
|
});
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,9 +7,14 @@ const State = @import("main.zig").State;
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const w4 = @import("wasm4.zig");
|
const w4 = @import("wasm4.zig");
|
||||||
const world = @import("world.zig");
|
const world = @import("world.zig");
|
||||||
|
const util = @import("util.zig");
|
||||||
|
|
||||||
const Vec2 = w4.Vec2;
|
const Vec2 = w4.Vec2;
|
||||||
|
|
||||||
|
var fba_buf: [1024]u8 = undefined;
|
||||||
|
var fba = std.heap.FixedBufferAllocator.init(&fba_buf);
|
||||||
|
var alloc = fba.allocator();
|
||||||
|
|
||||||
var frame_fba_buf: [4096]u8 = undefined;
|
var frame_fba_buf: [4096]u8 = undefined;
|
||||||
var frame_fba = std.heap.FixedBufferAllocator.init(&frame_fba_buf);
|
var frame_fba = std.heap.FixedBufferAllocator.init(&frame_fba_buf);
|
||||||
var frame_alloc = frame_fba.allocator();
|
var frame_alloc = frame_fba.allocator();
|
||||||
|
@ -21,10 +26,21 @@ 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 circuit_options: Circuit.Options = 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_options = .{
|
||||||
|
.map = &circuit_buf,
|
||||||
|
.levels = &circuit_lvl_buf,
|
||||||
|
.map_size = level_size,
|
||||||
|
.bridges = try alloc.alloc(Circuit.BridgeState, 5),
|
||||||
|
.sources = try alloc.alloc(util.Cell, 5),
|
||||||
|
.doors = try alloc.alloc(Circuit.DoorState, 5),
|
||||||
|
};
|
||||||
|
circuit = Circuit.init(circuit_options);
|
||||||
|
|
||||||
map = Map.init(&map_buf, level_size);
|
map = Map.init(&map_buf, level_size);
|
||||||
|
|
||||||
var stream = std.io.FixedBufferStream([]const u8){
|
var stream = std.io.FixedBufferStream([]const u8){
|
||||||
|
|
64
src/util.zig
64
src/util.zig
|
@ -64,19 +64,67 @@ pub const AABB = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn Queue(comptime T: type, len: usize) type {
|
pub fn Queue(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
data: std.BoundedArray(T, len),
|
begin: usize,
|
||||||
pub fn init() !@This() {
|
end: usize,
|
||||||
|
data: []T,
|
||||||
|
pub fn init(slice: []T) @This() {
|
||||||
return @This(){
|
return @This(){
|
||||||
.data = try std.BoundedArray(T, len).init(0),
|
.begin = 0,
|
||||||
|
.end = 0,
|
||||||
|
.data = slice,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn insert(this: *@This(), t: T) !void {
|
fn next(this: @This(), idx: usize) usize {
|
||||||
try this.data.insert(0, t);
|
return ((idx + 1) % this.data.len);
|
||||||
}
|
}
|
||||||
pub fn remove(this: *@This()) ?Cell {
|
pub fn insert(this: *@This(), t: T) !void {
|
||||||
return this.data.popOrNull();
|
const n = this.next(this.end);
|
||||||
|
if (n == this.begin) return error.OutOfMemory;
|
||||||
|
this.data[this.end] = t;
|
||||||
|
this.end = n;
|
||||||
|
}
|
||||||
|
pub fn remove(this: *@This()) ?T {
|
||||||
|
if (this.begin == this.end) return null;
|
||||||
|
const datum = this.data[this.begin];
|
||||||
|
this.begin = this.next(this.begin);
|
||||||
|
return datum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Queue" {
|
||||||
|
var items: [3]usize = undefined;
|
||||||
|
var q = Queue(usize).init(&items);
|
||||||
|
try q.insert(1);
|
||||||
|
try q.insert(2);
|
||||||
|
try std.testing.expectError(error.OutOfMemory, q.insert(3));
|
||||||
|
try std.testing.expectEqual(@as(?usize, 1), q.remove());
|
||||||
|
try std.testing.expectEqual(@as(?usize, 2), q.remove());
|
||||||
|
try std.testing.expectEqual(@as(?usize, null), q.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Buffer(comptime T: type) type {
|
||||||
|
return struct {
|
||||||
|
len: usize,
|
||||||
|
items: []T,
|
||||||
|
|
||||||
|
pub fn init(slice: []T) @This() {
|
||||||
|
return @This(){
|
||||||
|
.len = 0,
|
||||||
|
.items = slice,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(buf: @This()) void {
|
||||||
|
buf.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(buf: @This(), item: T) void {
|
||||||
|
std.debug.assert(buf.len < buf.items.len);
|
||||||
|
buf.items[buf.len] = item;
|
||||||
|
buf.len += 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue