Initial implementation of one way platforms
parent
d799830ad9
commit
8ad6d20fbd
|
@ -20,6 +20,9 @@ pub const Pos = struct {
|
||||||
pub fn initVel(pos: Vec2f, vel: Vec2f) @This() {
|
pub fn initVel(pos: Vec2f, vel: Vec2f) @This() {
|
||||||
return @This(){ .pos = pos, .last = pos - vel };
|
return @This(){ .pos = pos, .last = pos - vel };
|
||||||
}
|
}
|
||||||
|
pub fn getDirection(pos: Pos) Vec2f {
|
||||||
|
return pos.pos - pos.last;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pub const Control = struct {
|
pub const Control = struct {
|
||||||
controller: enum { player },
|
controller: enum { player },
|
||||||
|
@ -39,6 +42,7 @@ pub const Kinematic = struct {
|
||||||
col: AABB,
|
col: AABB,
|
||||||
move: Vec2f = Vec2f{ 0, 0 },
|
move: Vec2f = Vec2f{ 0, 0 },
|
||||||
lastCol: Vec2f = Vec2f{ 0, 0 },
|
lastCol: Vec2f = Vec2f{ 0, 0 },
|
||||||
|
pass_start: ?usize = null,
|
||||||
|
|
||||||
pub fn inAir(this: @This()) bool {
|
pub fn inAir(this: @This()) bool {
|
||||||
return approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
return approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
||||||
|
|
32
src/game.zig
32
src/game.zig
|
@ -328,7 +328,7 @@ pub fn update(time: usize) !State {
|
||||||
velocityProcess(1, &player.pos);
|
velocityProcess(1, &player.pos);
|
||||||
physicsProcess(1, &player.pos, &player.physics);
|
physicsProcess(1, &player.pos, &player.physics);
|
||||||
try manipulationProcess(&player.pos, &player.control);
|
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);
|
try kinematicProcess(1, &player.pos, &player.kinematic);
|
||||||
controlAnimProcess(1, &player.sprite, &player.controlAnim, &player.control);
|
controlAnimProcess(1, &player.sprite, &player.controlAnim, &player.control);
|
||||||
try particles.update();
|
try particles.update();
|
||||||
|
@ -727,12 +727,18 @@ fn controlAnimProcess(_: f32, sprite: *Sprite, anim: *ControlAnim, control: *Con
|
||||||
|
|
||||||
const approxEqAbs = std.math.approxEqAbs;
|
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 };
|
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 (approxEqAbs(f32, kinematic.move[1], 0, 0.01) and kinematic.lastCol[1] > 0) {
|
||||||
if (input.btnp(.one, .one)) delta[1] -= 23;
|
if (input.btnp(.one, .one)) delta[1] -= 23;
|
||||||
if (input.btn(.one, .left)) delta[0] -= 1;
|
if (input.btn(.one, .left)) delta[0] -= 1;
|
||||||
if (input.btn(.one, .right)) 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) {
|
if (delta[0] != 0 or delta[1] != 0) {
|
||||||
control.state = .walk;
|
control.state = .walk;
|
||||||
} else {
|
} else {
|
||||||
|
@ -759,9 +765,15 @@ fn controlProcess(_: f32, pos: *Pos, control: *Control, physics: *Physics, kinem
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void {
|
fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void {
|
||||||
|
const is_passing = kinematic.pass_start != null;
|
||||||
var next = pos.last;
|
var next = pos.last;
|
||||||
next[0] = pos.pos[0];
|
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) {
|
if (hcol.len > 0) {
|
||||||
kinematic.lastCol[0] = next[0] - pos.last[0];
|
kinematic.lastCol[0] = next[0] - pos.last[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];
|
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) {
|
if (vcol.len > 0) {
|
||||||
kinematic.lastCol[1] = next[1] - pos.last[1];
|
kinematic.lastCol[1] = next[1] - pos.last[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 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) {
|
if (lastCol.len == 0) {
|
||||||
kinematic.lastCol = Vec2f{ 0, 0 };
|
kinematic.lastCol = Vec2f{ 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
80
src/map.zig
80
src/map.zig
|
@ -107,6 +107,55 @@ fn getTile(this: @This(), x: i32, y: i32) ?u8 {
|
||||||
return this.tiles[@intCast(u32, i)];
|
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 {
|
pub const CollisionInfo = struct {
|
||||||
len: usize,
|
len: usize,
|
||||||
items: [9]util.AABB,
|
items: [9]util.AABB,
|
||||||
|
@ -125,35 +174,12 @@ pub const CollisionInfo = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn collide(this: @This(), rect: util.AABB) CollisionInfo {
|
pub fn isSolid(tile: u8) bool {
|
||||||
const top_left = rect.pos / tile_sizef;
|
return tile >= 2;
|
||||||
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(this: @This(), cell: Cell) bool {
|
pub fn isOneWay(tile: u8) bool {
|
||||||
if (this.get_cell(cell)) |tile| {
|
return tile >= 34 and tile <= 36;
|
||||||
return tile != 0 and tile != 1;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug functions
|
// Debug functions
|
||||||
|
|
Loading…
Reference in New Issue