Add music, fiddle with stack size

master
Louis Pearson 2022-01-21 16:26:32 -07:00
parent 199c206a6d
commit aebd05de18
3 changed files with 112 additions and 12 deletions

View File

@ -60,7 +60,7 @@ pub fn build(b: *std.build.Builder) !void {
lib.initial_memory = 65536;
lib.max_memory = 65536;
if (try version_supports_stack_first(zig_version)) {
lib.stack_size = 14752;
lib.stack_size = 24752;
} else {
// `--stack-first` option have been reenabled on wasm targets with https://github.com/ziglang/zig/pull/10572
std.log.warn("Update to Zig >=0.9.1 (or >=0.10.0-dev.258 for nightly) to detect stack overflows at runtime.", .{});

View File

@ -6,6 +6,7 @@ const input = @import("input.zig");
const util = @import("util.zig");
const Circuit = @import("circuit.zig");
const Map = @import("map.zig");
const Music = @import("music.zig");
const Vec2 = util.Vec2;
const Vec2f = util.Vec2f;
@ -147,7 +148,7 @@ fn randRangeF(min: f32, max: f32) f32 {
// Global vars
const KB = 1024;
var heap: [16 * KB]u8 = undefined;
var heap: [10 * KB]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&heap);
var world: World = World.init(fba.allocator());
var map: Map = undefined;
@ -156,6 +157,7 @@ var particles: ParticleSystem = undefined;
var prng = std.rand.DefaultPrng.init(0);
var random = prng.random();
var player: ?usize = null;
var music = Music.Procedural.init(.C3, &Music.Minor, 83);
const anim_store = struct {
const stand = Anim.frame(0);
@ -177,6 +179,8 @@ const playerAnim = pac: {
break :pac animArr.slice();
};
const WireQuery = World.Query.require(&.{.wire});
fn showErr(msg: []const u8) noreturn {
w4.traceNoF(msg);
unreachable;
@ -235,8 +239,7 @@ export fn update() void {
// Doing this before clearing the screen since the stack
// reaches the screen during this block
circuit.clear();
const q = World.Query.require(&.{.wire});
var wireIter = world.iter(q);
var wireIter = world.iter(WireQuery);
while (wireIter.next()) |wireID| {
const e = world.get(wireID);
const nodes = e.wire.?.nodes.constSlice();
@ -259,8 +262,6 @@ export fn update() void {
}
}
}
w4.DRAW_COLORS.* = 0x0004;
w4.rect(.{ 0, 0 }, .{ 160, 160 });
world.process(1, &.{.pos}, velocityProcess);
world.process(1, &.{ .pos, .physics }, physicsProcess);
@ -271,8 +272,12 @@ export fn update() void {
world.process(1, &.{ .pos, .kinematic }, kinematicProcess);
world.process(1, &.{ .sprite, .staticAnim }, staticAnimProcess);
world.process(1, &.{ .sprite, .controlAnim, .control }, controlAnimProcess);
world.process(1, &.{ .pos, .sprite }, drawProcess);
particles.update();
// Drawing
w4.DRAW_COLORS.* = 0x0004;
w4.rect(.{ 0, 0 }, .{ 160, 160 });
world.process(1, &.{ .pos, .sprite }, drawProcess);
map.draw();
for (circuit.cells) |cell, i| {
@ -287,7 +292,6 @@ export fn update() void {
world.process(1, &.{.wire}, wireDrawProcess);
particles.update();
particles.draw();
if (player) |p| {
@ -298,7 +302,10 @@ export fn update() void {
circuit.isEnabled(pos + util.Dir.left) or
circuit.isEnabled(pos + util.Dir.right);
if (shouldHum) {
w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 1, .{ .channel = .pulse1, .mode = .p50 });
// w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 1, .{ .channel = .pulse1, .mode = .p50 });
music.newIntensity = .active;
} else {
music.newIntensity = .calm;
}
}
@ -312,7 +319,8 @@ export fn update() void {
}
if (details.active) {
w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 10, .{ .channel = .pulse1, .mode = .p50 });
// w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 10, .{ .channel = .pulse1, .mode = .p50 });
music.newIntensity = .danger;
w4.DRAW_COLORS.* = 0x0020;
} else {
w4.DRAW_COLORS.* = 0x0030;
@ -325,6 +333,15 @@ export fn update() void {
}
}
// Music
const musicCommand = music.getNext(1);
if (musicCommand.freq) |freq| {
w4.tone(.{ .start = freq }, .{ .sustain = 2, .release = 2 }, 10, .{ .channel = .pulse2, .mode = .p50 });
}
if (musicCommand.drum) |drum| {
w4.tone(drum.freq, drum.duration, 10, .{ .channel = .triangle });
}
indicator = null;
input.update();
time += 1;
@ -396,8 +413,7 @@ fn wireManipulationProcess(_: f32, pos: *Pos, control: *Control) void {
} else {
const interactDistance = 4;
var minDistance: f32 = interactDistance;
const q = World.Query.require(&.{.wire});
var wireIter = world.iter(q);
var wireIter = world.iter(WireQuery);
var interactWireID: ?usize = null;
var which: usize = 0;
while (wireIter.next()) |entityID| {

84
src/music.zig Normal file
View File

@ -0,0 +1,84 @@
const w4 = @import("wasm4.zig");
const midiNote = [_]u16{
8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15,
15, 16, 17, 18, 19, 21, 22, 23, 24, 26, 28,
29, 31, 33, 35, 37, 39, 41, 44, 46, 49, 52,
55, 58, 62, 65, 69, 73, 78, 82, 87, 92, 98,
104, 110, 117, 123, 131, 139, 147, 156, 165, 175, 185,
196, 208, 220, 233, 247, 262, 277, 294, 311, 330, 349,
370, 392, 415, 440, 466, 494, 523, 554, 587, 622, 659,
698, 740, 784, 831, 880, 932, 988, 1047, 1109, 1175, 1245,
1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, 2349,
2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, 4186, 4435,
4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902, 8372,
8870, 9397, 9956, 10548, 11175, 11840, 12544,
};
pub const Note = enum(usize) { C3 = 57, C4 = 69 };
// Defines steps along a musical scale
pub const Major = [8]usize{ 0, 2, 4, 5, 7, 9, 11, 12 };
pub const Minor = [8]usize{ 0, 2, 3, 5, 7, 8, 11, 12 };
pub const MusicCommand = struct {
freq: ?u16 = null,
drum: ?struct { freq: w4.ToneFrequency, duration: w4.ToneDuration } = null,
};
pub const Intensity = enum(u8) {
calm = 0,
active = 1,
danger = 2,
pub fn atLeast(lhs: @This(), rhs: @This()) bool {
return @enumToInt(lhs) >= @enumToInt(rhs);
}
};
pub const Procedural = struct {
tick: usize,
note: usize,
beat: usize,
beatsPerBar: usize,
seed: usize,
root: usize,
scale: []const usize,
intensity: Intensity = .calm,
newIntensity: ?Intensity = null,
pub fn init(root: Note, scale: []const usize, seed: usize) @This() {
return @This(){
.tick = 0,
.beat = 15,
.beatsPerBar = 6,
.seed = seed,
.root = @enumToInt(root),
.scale = scale,
.note = 0,
};
}
pub fn getNext(this: *@This(), dt: u32) MusicCommand {
var cmd = MusicCommand{};
const beatProgress = this.tick % this.beat;
const beatTotal = @divTrunc(this.tick, this.beat);
const beat = beatTotal % this.beatsPerBar;
const bar = @divTrunc(beat, this.beatsPerBar);
this.tick += dt;
if (beat == 0) this.intensity = this.newIntensity orelse this.intensity;
if (this.intensity.atLeast(.active) and bar % 2 == 0 and beatProgress == 0) {
cmd.freq = midiNote[this.root + this.scale[((this.seed * this.note) % 313) % 8]];
this.note += 1;
}
if (this.intensity.atLeast(.calm) and beat == 0) cmd.drum = .{
.freq = .{ .start = 100, .end = 1 },
.duration = .{ .sustain = 1, .release = 4 },
};
if (this.intensity.atLeast(.danger) and beat % 3 == 1) cmd.drum = .{
.freq = .{ .start = 1761 },
.duration = .{ .release = 6 },
};
return cmd;
}
};