diff --git a/src/ecs.zig b/src/ecs.zig index 099e3b3..43517eb 100644 --- a/src/ecs.zig +++ b/src/ecs.zig @@ -79,9 +79,9 @@ pub fn World(comptime ComponentBase: type) type { }; } - pub fn create(this: *@This(), component: Component) usize { + pub fn create(this: *@This(), component: Component) !usize { const len = this.components.len; - this.components.append(this.alloc, component) catch unreachable; + try this.components.append(this.alloc, component); return len; } @@ -92,7 +92,7 @@ pub fn World(comptime ComponentBase: type) type { @compileError("unimplemented"); } - pub fn get(this: *@This(), entity: usize, component: ComponentEnum) *Component { + pub fn get(this: *@This(), entity: usize, comptime component: ComponentEnum) *Component { return this.components.items(component)[entity]; } diff --git a/src/main.zig b/src/main.zig index 536c227..cc0ff5b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,6 +4,7 @@ const ecs = @import("ecs.zig"); const assets = @import("assets"); const Vec2f = std.meta.Vector(2, f32); +const AABB = struct { offset: Vec2f, size: Vec2f }; const Anim = struct { time: usize = 0, currentOp: usize = 0, @@ -53,21 +54,25 @@ const Control = struct { state: enum { stand, walk, jump, fall }, facing: enum { left, right } = .right, }; -const Sprite = struct { index: usize, flags: w4.BlitFlags }; +const Sprite = struct { offset: Vec2f = Vec2f{ 0, 0 }, size: w4.Vec2, index: usize, flags: w4.BlitFlags }; const StaticAnim = Anim; const ControlAnim = struct { anims: []AnimData, state: Anim }; +const Kinematic = struct { col: AABB }; +const Wire = struct { end: Vec2f, grabbed: ?enum { begin, end } = null }; const Component = struct { pos: Pos, control: Control, sprite: Sprite, staticAnim: StaticAnim, controlAnim: ControlAnim, + kinematic: Kinematic, + wire: Wire, }; const World = ecs.World(Component); // Global vars const KB = 1024; -var heap: [1 * KB]u8 = undefined; +var heap: [8 * KB]u8 = undefined; var fba = std.heap.FixedBufferAllocator.init(&heap); var world: World = World.init(fba.allocator()); @@ -93,18 +98,36 @@ export fn start() void { _ = world.create(.{ .pos = .{ 76, 76 }, .control = .{ .controller = .player, .state = .stand }, - .sprite = .{ .index = 0, .flags = .{ .bpp = .b1 } }, + .sprite = .{ .offset = .{ -4, -8 }, .size = .{ 8, 8 }, .index = 0, .flags = .{ .bpp = .b1 } }, .controlAnim = ControlAnim{ .anims = playerAnim, .state = Anim{ .anim = &.{} }, }, - }); + .kinematic = .{ .col = .{ .offset = .{ -2, -8 }, .size = .{ 4, 8 } } }, + }) catch unreachable; + + for (assets.wire) |wire| { + w4.trace("begin {}, end {}", .{ wire[0], wire[1] }); + const begin = Vec2f{ @intToFloat(f32, wire[0][0]), @intToFloat(f32, wire[0][1]) }; + const end = Vec2f{ @intToFloat(f32, wire[1][0]), @intToFloat(f32, wire[1][1]) }; + w4.trace("{}, {}, begin {d:3.0}, end {d:3.0}", .{ wire[0], wire[1], begin, end }); + const w = Wire{ .end = end }; + const e = world.create(.{ + .pos = begin, + .wire = w, + }) catch { + w4.trace("problem", .{}); + unreachable; + }; + w4.trace("{}", .{world.components.items(.wire)[e]}); + } } export fn update() void { w4.DRAW_COLORS.* = 0x0004; w4.rect(.{ 0, 0 }, .{ 160, 160 }); + world.process(1, &.{ .pos, .kinematic }, kinematicProcess); world.process(1, &.{ .pos, .control }, controlProcess); world.process(1, &.{ .sprite, .staticAnim }, staticAnimProcess); world.process(1, &.{ .sprite, .controlAnim, .control }, controlAnimProcess); @@ -124,17 +147,67 @@ export fn update() void { } } + world.process(1, &.{ .pos, .wire }, wireProcess); + // for (assets.wire) |wire| { + // w4.DRAW_COLORS.* = 0x0001; + // w4.line(wire[0], wire[1]); + // w4.DRAW_COLORS.* = 0x0031; + // if (distance(wire[0], w4.MOUSE.pos()) < 8) w4.oval(wire[0] - w4.Vec2{ 2, 2 }, w4.Vec2{ 5, 5 }); + // if (distance(wire[1], w4.MOUSE.pos()) < 8) w4.oval(wire[1] - w4.Vec2{ 2, 2 }, w4.Vec2{ 5, 5 }); + // } + + mouseLast = w4.MOUSE.buttons.left; +} + +fn distance(a: w4.Vec2, b: w4.Vec2) i32 { + var subbed = a - b; + subbed[0] = std.math.absInt(subbed[0]) catch unreachable; + subbed[1] = std.math.absInt(subbed[1]) catch unreachable; + return @reduce(.Max, subbed); +} + +var mouseLast = false; + +fn wireProcess(_: f32, pos: *Pos, wire: *Wire) void { + const begin = w4.Vec2{ @floatToInt(i32, pos.*[0]), @floatToInt(i32, pos.*[1]) }; + const end = w4.Vec2{ @floatToInt(i32, wire.end[0]), @floatToInt(i32, wire.end[1]) }; + // if (w4.MOUSE.buttons.left and !mouseLast) w4.trace("pos {}, wire {}, begin {}, end {}", .{ pos.*, wire.end, begin, end }); w4.DRAW_COLORS.* = 0x0001; - for (assets.wire) |wire| { - w4.line(wire[0], wire[1]); + w4.line(begin, end); + w4.DRAW_COLORS.* = 0x0031; + + if (wire.grabbed) |whichEnd| { + switch (whichEnd) { + .begin => pos.* = vec2tovec2f(w4.MOUSE.pos()), + .end => wire.end = vec2tovec2f(w4.MOUSE.pos()), + } + if (w4.MOUSE.buttons.left and !mouseLast) wire.grabbed = null; + } else { + if (distance(begin, w4.MOUSE.pos()) < 8) { + w4.oval(begin - w4.Vec2{ 2, 2 }, w4.Vec2{ 5, 5 }); + if (w4.MOUSE.buttons.left and !mouseLast) wire.grabbed = .begin; + } + if (distance(end, w4.MOUSE.pos()) < 8) { + w4.oval(end - w4.Vec2{ 2, 2 }, w4.Vec2{ 5, 5 }); + if (w4.MOUSE.buttons.left and !mouseLast) wire.grabbed = .end; + } } } +fn vec2tovec2f(vec2: w4.Vec2) Vec2f { + return Vec2f{ @intToFloat(f32, vec2[0]), @intToFloat(f32, vec2[1]) }; +} + +fn vec2ftovec2(vec2f: Vec2f) w4.Vec2 { + return w4.Vec2{ @floatToInt(i32, vec2f[0]), @intToFloat(i32, vec2f[1]) }; +} + fn drawProcess(_: f32, pos: *Pos, sprite: *Sprite) void { w4.DRAW_COLORS.* = 0x0010; - const ipos = w4.Vec2{ @floatToInt(i32, pos.*[0]), @floatToInt(i32, pos.*[1]) }; + const fpos = pos.* + sprite.offset; + const ipos = w4.Vec2{ @floatToInt(i32, fpos[0]), @floatToInt(i32, fpos[1]) }; const t = w4.Vec2{ @intCast(i32, (sprite.index * 8) % 128), @intCast(i32, (sprite.index * 8) / 128) }; - w4.blitSub(&assets.sprites, ipos, .{ 8, 8 }, t, 128, sprite.flags); + w4.blitSub(&assets.sprites, ipos, sprite.size, t, 128, sprite.flags); } fn staticAnimProcess(_: f32, sprite: *Sprite, anim: *StaticAnim) void { @@ -157,11 +230,14 @@ fn controlProcess(_: f32, pos: *Pos, control: *Control) void { if (delta[0] != 0 or delta[1] != 0) { control.state = .walk; pos.* += delta; - if (pos.*[0] < 0) pos.*[0] = 0; - if (pos.*[0] > 152) pos.*[0] = 152; - if (delta[0] > 0) control.facing = .right; - if (delta[0] < 0) control.facing = .left; } else { control.state = .stand; } } + +fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) void { + pos.* += Vec2f{ 0, 1 }; + var topleft = pos.* + kinematic.col.offset; + var bottomright = topleft + kinematic.col.size; + if (bottomright[1] > 160) pos.*[1] = 160 - (kinematic.col.offset[1] + kinematic.col.size[1]); +}