From 2f2e1e7de14c858c72ccc1f807fe0504aed33210 Mon Sep 17 00:00:00 2001 From: Kurtis Melby Date: Sun, 6 Oct 2024 20:37:22 -0400 Subject: [PATCH] fix: slope collision detection is inconsistent --- .../collision_detection_behavior.dart | 67 ++++++++++--------- .../leap/lib/src/entities/collision_info.dart | 7 ++ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/packages/leap/lib/src/entities/behaviors/collision_detection_behavior.dart b/packages/leap/lib/src/entities/behaviors/collision_detection_behavior.dart index caccaad..b240bc2 100644 --- a/packages/leap/lib/src/entities/behaviors/collision_detection_behavior.dart +++ b/packages/leap/lib/src/entities/behaviors/collision_detection_behavior.dart @@ -88,26 +88,29 @@ class CollisionDetectionBehavior extends PhysicalBehavior _tmpHits.sort((a, b) => a.left.compareTo(b.left)); final firstRightHit = _tmpHits.first; if (firstRightHit.isSlopeFromLeft) { - if (velocity.y >= 0) { - // Ignore slope underneath while moving upwards. - collisionInfo.addDownCollision(firstRightHit); - } else { - collisionInfo.addRightCollision(firstRightHit); - } + collisionInfo.addDownCollision(firstRightHit); } else if (firstRightHit.isPitchFromRight) { - if (velocity.y <= 0) { - // Ignore pitch above while moving down. - collisionInfo.addUpCollision(firstRightHit); - } else { - collisionInfo.addRightCollision(firstRightHit); - } + collisionInfo.addUpCollision(firstRightHit); } else if (firstRightHit.left >= right) { - _tmpHits - .where((c) => c.left == firstRightHit.left) - .forEach(collisionInfo.addRightCollision); + _tmpHits.where((c) => c.left == firstRightHit.left).forEach((c) { + if (c.isSlopeFromLeft) { + collisionInfo.addDownCollision(c); + } else if (prevCollisionInfo.onSlope && + prevCollisionInfo.downCollision!.top == c.top) { + collisionInfo.addDownCollision(c); + } else if (c.isPitchFromRight) { + collisionInfo.addUpCollision(c); + } else if (prevCollisionInfo.onPitch && + prevCollisionInfo.upCollision!.bottom == c.bottom) { + collisionInfo.addUpCollision(c); + } else { + collisionInfo.addRightCollision(c); + } + }); } } } + if (velocity.x < 0) { // Moving left. _calculateSolidHits((c) { @@ -120,25 +123,25 @@ class CollisionDetectionBehavior extends PhysicalBehavior _tmpHits.sort((a, b) => b.right.compareTo(a.right)); final firstLeftHit = _tmpHits.first; if (firstLeftHit.isSlopeFromRight) { - // Ignore slope underneath while moving upwards, should not collide - // on left. - if (velocity.y >= 0) { - collisionInfo.addDownCollision(firstLeftHit); - } else { - collisionInfo.addLeftCollision(firstLeftHit); - } + collisionInfo.addDownCollision(firstLeftHit); } else if (firstLeftHit.isPitchFromLeft) { - // Ignore pitch above while moving downward, should not collide - // on left. - if (velocity.y <= 0) { - collisionInfo.addUpCollision(firstLeftHit); - } else { - collisionInfo.addLeftCollision(firstLeftHit); - } + collisionInfo.addUpCollision(firstLeftHit); } else if (firstLeftHit.right <= left) { - _tmpHits - .where((c) => c.right == firstLeftHit.right) - .forEach(collisionInfo.addLeftCollision); + _tmpHits.where((c) => c.right == firstLeftHit.right).forEach((c) { + if (c.isSlopeFromRight) { + collisionInfo.addDownCollision(c); + } else if (prevCollisionInfo.onSlope && + prevCollisionInfo.downCollision!.top == c.top) { + collisionInfo.addDownCollision(c); + } else if (c.isPitchFromLeft) { + collisionInfo.addUpCollision(c); + } else if (prevCollisionInfo.onPitch && + prevCollisionInfo.upCollision!.bottom == c.bottom) { + collisionInfo.addUpCollision(c); + } else { + collisionInfo.addLeftCollision(c); + } + }); } } } diff --git a/packages/leap/lib/src/entities/collision_info.dart b/packages/leap/lib/src/entities/collision_info.dart index 3f9f118..4c16e73 100644 --- a/packages/leap/lib/src/entities/collision_info.dart +++ b/packages/leap/lib/src/entities/collision_info.dart @@ -116,6 +116,13 @@ class CollisionInfo { return !up && !down && !left && !right; } + bool get onPitch { + if (upCollision != null && upCollision is LeapMapGroundTile) { + return (upCollision! as LeapMapGroundTile).isPitch; + } + return false; + } + bool get onSlope { if (downCollision != null && downCollision is LeapMapGroundTile) { return (downCollision! as LeapMapGroundTile).isSlope;