Skip to content

Commit

Permalink
fix: fix incorrect ground state detection when intersecting jump-thro…
Browse files Browse the repository at this point in the history
…ugh tiles. (#708)

Closes: #705
  • Loading branch information
zicklag authored Mar 10, 2023
1 parent 4524d9d commit 5f743f4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
34 changes: 30 additions & 4 deletions core/src/physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,42 @@ fn update_kinematic_bodies(
// Check ground collision
{
let mut transform = transforms.get(entity).copied().unwrap();

// Don't get stuck floating in fall-through platforms
if body.velocity == Vec2::ZERO
&& collision_world.tile_collision_filtered(transform, body.shape, |ent| {
collision_world
.tile_collision_kinds
.get(ent)
.map(|x| *x == TileCollisionKind::JumpThrough)
.unwrap_or(false)
}) == TileCollisionKind::JumpThrough
{
body.fall_through = true;
}

// Move transform check down 1 slightly
transform.translation.y -= 0.1;

body.was_on_ground = body.is_on_ground;

let tile = collision_world.tile_collision(transform, body.shape);
let collider = collision_world.get_collider(entity);

let tile = collision_world.tile_collision_filtered(transform, body.shape, |ent| {
if collider.seen_wood {
collision_world
.tile_collision_kinds
.get(ent)
.map(|x| *x != TileCollisionKind::JumpThrough)
.unwrap_or(false)
} else {
true
}
});

let on_jump_through_tile = tile == TileCollisionKind::JumpThrough;
body.is_on_ground = tile != TileCollisionKind::Empty
&& !collision_world.get_collider(entity).seen_wood
&& !(on_jump_through_tile && body.fall_through);
body.is_on_ground =
tile != TileCollisionKind::Empty && !(on_jump_through_tile && body.fall_through);
body.is_on_platform = body.is_on_ground && on_jump_through_tile;
}

Expand Down
11 changes: 10 additions & 1 deletion core/src/physics/collisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,15 @@ impl<'a> CollisionWorld<'a> {
/// Get the [`TileCollisionKind`] of the first tile detected colliding with the `shape` at the
/// given `transform`.
pub fn tile_collision(&self, transform: Transform, shape: ColliderShape) -> TileCollisionKind {
self.tile_collision_filtered(transform, shape, |_| true)
}

pub fn tile_collision_filtered(
&self,
transform: Transform,
shape: ColliderShape,
filter: impl Fn(Entity) -> bool,
) -> TileCollisionKind {
self.ctx
.query_pipeline
.intersection_with_shape(
Expand All @@ -883,7 +892,7 @@ impl<'a> CollisionWorld<'a> {
&*shape.shared_shape(),
rapier::QueryFilter::new().predicate(&|_handle, collider| {
let ent = RapierUserData::entity(collider.user_data);
self.tile_collision_kinds.contains(ent)
self.tile_collision_kinds.contains(ent) && filter(ent)
}),
)
.map(|x| RapierUserData::entity(self.ctx.collider_set.get(x).unwrap().user_data))
Expand Down

0 comments on commit 5f743f4

Please sign in to comment.