diff --git a/src/component.zig b/src/component.zig index 6874478..a55f14d 100644 --- a/src/component.zig +++ b/src/component.zig @@ -20,6 +20,9 @@ pub const Pos = struct { pub fn initVel(pos: Vec2f, vel: Vec2f) @This() { return @This(){ .pos = pos, .last = pos - vel }; } + pub fn getDirection(pos: Pos) Vec2f { + return pos.pos - pos.last; + } }; pub const Control = struct { controller: enum { player }, @@ -39,6 +42,7 @@ pub const Kinematic = struct { col: AABB, move: Vec2f = Vec2f{ 0, 0 }, lastCol: Vec2f = Vec2f{ 0, 0 }, + pass_start: ?usize = null, pub fn inAir(this: @This()) bool { return approxEqAbs(f32, this.lastCol[1], 0, 0.01); diff --git a/src/game.zig b/src/game.zig index 02c3211..e8faf44 100644 --- a/src/game.zig +++ b/src/game.zig @@ -328,7 +328,7 @@ pub fn update(time: usize) !State { velocityProcess(1, &player.pos); physicsProcess(1, &player.pos, &player.physics); try manipulationProcess(&player.pos, &player.control); - controlProcess(1, &player.pos, &player.control, &player.physics, &player.kinematic); + controlProcess(time, &player.pos, &player.control, &player.physics, &player.kinematic); try kinematicProcess(1, &player.pos, &player.kinematic); controlAnimProcess(1, &player.sprite, &player.controlAnim, &player.control); try particles.update(); @@ -727,12 +727,18 @@ fn controlAnimProcess(_: f32, sprite: *Sprite, anim: *ControlAnim, control: *Con const approxEqAbs = std.math.approxEqAbs; -fn controlProcess(_: f32, pos: *Pos, control: *Control, physics: *Physics, kinematic: *Kinematic) void { +fn controlProcess(time: usize, pos: *Pos, control: *Control, physics: *Physics, kinematic: *Kinematic) void { var delta = Vec2f{ 0, 0 }; + if (kinematic.pass_start) |pass_start| { + if (time - pass_start > 10) { + kinematic.pass_start = null; + } + } if (approxEqAbs(f32, kinematic.move[1], 0, 0.01) and kinematic.lastCol[1] > 0) { if (input.btnp(.one, .one)) delta[1] -= 23; if (input.btn(.one, .left)) delta[0] -= 1; if (input.btn(.one, .right)) delta[0] += 1; + if (input.btn(.one, .down)) kinematic.pass_start = time; if (delta[0] != 0 or delta[1] != 0) { control.state = .walk; } else { @@ -759,9 +765,15 @@ fn controlProcess(_: f32, pos: *Pos, control: *Control, physics: *Physics, kinem } fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void { + const is_passing = kinematic.pass_start != null; var next = pos.last; next[0] = pos.pos[0]; - var hcol = map.collide(kinematic.col.addv(next)); + var hcol = map.collide(.{ + .rect = kinematic.col.addv(next), + .last = pos.last, + .next = next, + .is_passing = is_passing, + }); if (hcol.len > 0) { kinematic.lastCol[0] = next[0] - pos.last[0]; next[0] = pos.last[0]; @@ -770,7 +782,12 @@ fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void { } next[1] = pos.pos[1]; - var vcol = map.collide(kinematic.col.addv(next)); + var vcol = map.collide(.{ + .rect = kinematic.col.addv(next), + .last = pos.last, + .next = next, + .is_passing = is_passing, + }); if (vcol.len > 0) { kinematic.lastCol[1] = next[1] - pos.last[1]; next[1] = pos.last[1]; @@ -779,7 +796,12 @@ fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void { } var colPosAbs = next + kinematic.lastCol; - var lastCol = map.collide(kinematic.col.addv(colPosAbs)); + var lastCol = map.collide(.{ + .rect = kinematic.col.addv(colPosAbs), + .last = pos.last, + .next = next, + .is_passing = is_passing, + }); if (lastCol.len == 0) { kinematic.lastCol = Vec2f{ 0, 0 }; } diff --git a/src/map.zig b/src/map.zig index 0ccf8b1..0416adb 100644 --- a/src/map.zig +++ b/src/map.zig @@ -107,6 +107,55 @@ fn getTile(this: @This(), x: i32, y: i32) ?u8 { return this.tiles[@intCast(u32, i)]; } +pub const BodyInfo = struct { + /// Rectangle + rect: util.AABB, + /// Last position + last: Vec2f, + /// Next position + next: Vec2f, + /// Pass through one way platforms + is_passing: bool = false, +}; + +pub fn collide(this: @This(), body: BodyInfo) CollisionInfo { + const top_left = body.rect.pos / tile_sizef; + const bot_right = (body.rect.pos + body.rect.size) / tile_sizef; + var collisions = CollisionInfo.init(); + + var i: isize = @floatToInt(i32, top_left[0]); + while (i <= @floatToInt(i32, bot_right[0])) : (i += 1) { + var a: isize = @floatToInt(i32, top_left[1]); + while (a <= @floatToInt(i32, bot_right[1])) : (a += 1) { + + const tile = this.getTile(i, a) orelse continue; + const tilex = @intToFloat(f32, i * tile_width); + const tiley = @intToFloat(f32, a * tile_height); + const bottom = @floatToInt(i32, bot_right[1]); + + if (isOneWay(tile)) { + // const last = @floatToInt(i32, body.last[1]); + // const next = @floatToInt(i32, body.next[1]); + // w4.tracef("%d, %d, %d", last, next, a * tile_height); + if (!body.is_passing and a == bottom and body.last[1] <= body.next[1]) { + collisions.append(util.AABB{ + .pos = Vec2f{tilex, tiley}, + .size = tile_sizef, + }); + } + } else if (isSolid(tile)) { + collisions.append(util.AABB{ + .pos = Vec2f{tilex, tiley}, + .size = tile_sizef, + }); + } + + } + } + + return collisions; +} + pub const CollisionInfo = struct { len: usize, items: [9]util.AABB, @@ -125,35 +174,12 @@ pub const CollisionInfo = struct { } }; -pub fn collide(this: @This(), rect: util.AABB) CollisionInfo { - const top_left = rect.pos / tile_sizef; - const bot_right = (rect.pos + rect.size) / tile_sizef; - var collisions = CollisionInfo.init(); - - var i: isize = @floatToInt(i32, top_left[0]); - while (i <= @floatToInt(i32, bot_right[0])) : (i += 1) { - var a: isize = @floatToInt(i32, top_left[1]); - while (a <= @floatToInt(i32, bot_right[1])) : (a += 1) { - if (this.isSolid(Cell{ i, a })) { - collisions.append(util.AABB{ - .pos = Vec2f{ - @intToFloat(f32, i * tile_width), - @intToFloat(f32, a * tile_height), - }, - .size = tile_sizef, - }); - } - } - } - - return collisions; +pub fn isSolid(tile: u8) bool { + return tile >= 2; } -pub fn isSolid(this: @This(), cell: Cell) bool { - if (this.get_cell(cell)) |tile| { - return tile != 0 and tile != 1; - } - return true; +pub fn isOneWay(tile: u8) bool { + return tile >= 34 and tile <= 36; } // Debug functions