Initial implementation of one way platforms

master
Louis Pearson 2022-08-04 20:39:28 -06:00
parent d799830ad9
commit 8ad6d20fbd
3 changed files with 84 additions and 32 deletions

View File

@ -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);

View File

@ -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 };
}

View File

@ -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