Add particles
parent
7931f03738
commit
313c058ae3
101
src/main.zig
101
src/main.zig
|
@ -20,6 +20,9 @@ const Pos = struct {
|
|||
pub fn init(pos: Vec2f) @This() {
|
||||
return @This(){ .pos = pos, .last = pos };
|
||||
}
|
||||
pub fn initVel(pos: Vec2f, vel: Vec2f) @This() {
|
||||
return @This(){ .pos = pos, .last = pos - vel };
|
||||
}
|
||||
};
|
||||
const Control = struct {
|
||||
controller: enum { player },
|
||||
|
@ -51,7 +54,18 @@ const Kinematic = struct {
|
|||
return this.isFalling() and !approxEqAbs(f32, this.lastCol[0], 0, 0.01);
|
||||
}
|
||||
};
|
||||
const Wire = struct { nodes: std.BoundedArray(Pos, 32), enabled: bool = false };
|
||||
const Wire = struct {
|
||||
nodes: std.BoundedArray(Pos, 32),
|
||||
enabled: bool = false,
|
||||
|
||||
pub fn begin(this: *@This()) *Pos {
|
||||
return &this.nodes.slice()[0];
|
||||
}
|
||||
|
||||
pub fn end(this: *@This()) *Pos {
|
||||
return &this.nodes.slice()[this.nodes.len - 1];
|
||||
}
|
||||
};
|
||||
const Physics = struct { gravity: Vec2f, friction: Vec2f };
|
||||
const Component = struct {
|
||||
pos: Pos,
|
||||
|
@ -65,6 +79,72 @@ const Component = struct {
|
|||
};
|
||||
const World = ecs.World(Component);
|
||||
|
||||
const Particle = struct {
|
||||
pos: Pos,
|
||||
life: i32,
|
||||
pub fn init(pos: Pos, life: i32) @This() {
|
||||
return @This(){
|
||||
.pos = pos,
|
||||
.life = life,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const ParticleSystem = struct {
|
||||
const MAXPARTICLES = 32;
|
||||
particles: std.BoundedArray(Particle, MAXPARTICLES),
|
||||
pub fn init() @This() {
|
||||
return @This(){
|
||||
.particles = std.BoundedArray(Particle, MAXPARTICLES).init(0) catch unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(this: *@This()) void {
|
||||
var physics = .{ .gravity = Vec2f{ 0, 0.1 }, .friction = Vec2f{ 0.1, 0.1 } };
|
||||
var remove = std.BoundedArray(usize, MAXPARTICLES).init(0) catch unreachable;
|
||||
for (this.particles.slice()) |*part, i| {
|
||||
velocityProcess(1, &part.pos);
|
||||
physicsProcess(1, &part.pos, &physics);
|
||||
part.life -= 1;
|
||||
if (part.life == 0) remove.append(i) catch unreachable;
|
||||
}
|
||||
while (remove.popOrNull()) |i| {
|
||||
_ = this.particles.swapRemove(i);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(this: @This()) void {
|
||||
for (this.particles.constSlice()) |*part| {
|
||||
w4.DRAW_COLORS.* = 0x0001;
|
||||
w4.oval(util.vec2fToVec2(part.pos.pos), Vec2{ 2, 2 });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createRandom(this: *@This(), pos: Vec2f) void {
|
||||
if (this.particles.len == this.particles.capacity()) return;
|
||||
const vel = Vec2f{ randRangeF(-1, 1), randRangeF(-2, 0) };
|
||||
const posComp = Pos.initVel(pos, vel);
|
||||
const life = randRange(10, 50);
|
||||
const part = Particle.init(posComp, life);
|
||||
this.particles.append(part) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn createNRandom(this: *@This(), pos: Vec2f, n: usize) void {
|
||||
var i: usize = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
this.createRandom(pos);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn randRange(min: i32, max: i32) i32 {
|
||||
return random.intRangeLessThanBiased(i32, min, max);
|
||||
}
|
||||
|
||||
fn randRangeF(min: f32, max: f32) f32 {
|
||||
return min + (random.float(f32) * (max - min));
|
||||
}
|
||||
|
||||
// Global vars
|
||||
const KB = 1024;
|
||||
var heap: [16 * KB]u8 = undefined;
|
||||
|
@ -72,6 +152,9 @@ var fba = std.heap.FixedBufferAllocator.init(&heap);
|
|||
var world: World = World.init(fba.allocator());
|
||||
var map: Map = undefined;
|
||||
var circuit: Circuit = undefined;
|
||||
var particles: ParticleSystem = undefined;
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
var random = prng.random();
|
||||
|
||||
const anim_store = struct {
|
||||
const stand = Anim.frame(0);
|
||||
|
@ -94,11 +177,13 @@ const playerAnim = pac: {
|
|||
};
|
||||
|
||||
fn showErr(msg: []const u8) noreturn {
|
||||
w4.trace("{s}", .{msg});
|
||||
w4.traceNoF(msg);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
export fn start() void {
|
||||
particles = ParticleSystem.init();
|
||||
|
||||
circuit = Circuit.init();
|
||||
map = Map.init(fba.allocator()) catch showErr("Init map");
|
||||
|
||||
|
@ -106,7 +191,7 @@ export fn start() void {
|
|||
circuit.load(mapPos, &assets.conduit, assets.conduit_size);
|
||||
map.load(mapPos, &assets.solid, assets.solid_size);
|
||||
|
||||
w4.trace("{}, {}, {}", .{ assets.spawn, mapPos, assets.spawn - mapPos });
|
||||
// w4.trace("{}, {}, {}", .{ assets.spawn, mapPos, assets.spawn - mapPos });
|
||||
|
||||
_ = world.create(.{
|
||||
.pos = Pos.init(util.vec2ToVec2f((assets.spawn - mapPos) * Map.tile_size) + Vec2f{ 4, 8 }),
|
||||
|
@ -166,7 +251,12 @@ export fn update() void {
|
|||
var wireComponents = world.components.items(.wire);
|
||||
var enabledWires = circuit.enabledBridges();
|
||||
for (enabledWires.slice()) |wireID| {
|
||||
wireComponents[wireID].?.enabled = true;
|
||||
var wire = wireComponents[wireID].?;
|
||||
wire.enabled = true;
|
||||
if (time % 60 == 0) {
|
||||
if (!wire.begin().pinned) particles.createNRandom(wire.begin().pos, 8);
|
||||
if (!wire.end().pinned) particles.createNRandom(wire.end().pos, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +285,9 @@ export fn update() void {
|
|||
|
||||
world.process(1, &.{.wire}, wireDrawProcess);
|
||||
|
||||
particles.update();
|
||||
particles.draw();
|
||||
|
||||
if (indicator) |details| {
|
||||
const pos = details.pos;
|
||||
const stage = @divTrunc((time % 60), 30);
|
||||
|
|
|
@ -352,6 +352,9 @@ pub fn trace(comptime fmt: []const u8, args: anytype) void {
|
|||
traceUtf8(&buffer, fbs.pos);
|
||||
}
|
||||
}
|
||||
pub fn traceNoF(msg: []const u8) void {
|
||||
traceUtf8(msg.ptr, msg.len);
|
||||
}
|
||||
extern fn traceUtf8(str_ptr: [*]const u8, str_len: usize) void;
|
||||
|
||||
/// Use with caution, as there's no compile-time type checking.
|
||||
|
|
Loading…
Reference in New Issue