From 695ff4da42aef93f43f8474b7a38820fa54ba833 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Sat, 11 Apr 2020 19:21:12 -0700 Subject: [PATCH] Collision: Fix clipping thru left walls, w/ caveats There was a clipping bug where the player could sometimes clip thru a left-side wall, if the left wall and floor made a 90 degree bend and the player was holding the Left key while jumping slightly into the wall. A band-aid that seems to work involved two steps: 1. When capping their leftward movement, add a "+ 1" to the cap. 2. At the start of the point loop, enforce the left cap like we do the ceiling cap. This seems to patch the problem, BUT it breaks the ability to walk up slopes while moving left. Right-facing slopes can be climbed fine still. Note: the original bug never was a problem against right walls, only left ones, but the true root cause was not identified. See TODO comments in collide_level.go. --- pkg/balance/numbers.go | 1 + pkg/collision/collide_level.go | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/pkg/balance/numbers.go b/pkg/balance/numbers.go index 1697cbf..0d23bd4 100644 --- a/pkg/balance/numbers.go +++ b/pkg/balance/numbers.go @@ -17,6 +17,7 @@ var ( PlayerMaxVelocity float64 = 6 PlayerAcceleration float64 = 0.2 Gravity float64 = 6 + SlopeMaxHeight = 8 // max pixel height for player to walk up a slope // Default chunk size for canvases. ChunkSize = 128 diff --git a/pkg/collision/collide_level.go b/pkg/collision/collide_level.go index 19e9c4d..ac960cd 100644 --- a/pkg/collision/collide_level.go +++ b/pkg/collision/collide_level.go @@ -3,6 +3,7 @@ package collision import ( "sync" + "git.kirsle.net/apps/doodle/pkg/balance" "git.kirsle.net/apps/doodle/pkg/level" "git.kirsle.net/go/render" ) @@ -117,7 +118,7 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli } else { height -= result.RightPoint.Y } - if height <= 8 { + if height <= balance.SlopeMaxHeight { target.Y -= height if target.X < P.X { target.X-- // push along to the left @@ -147,6 +148,11 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli if capHeight != 0 && point.Y < capHeight { point.Y = capHeight } + if capLeft != 0 && point.X < capLeft { + // TODO: this along with a "+ 1" hack prevents clipping thru the + // left wall sometimes, but breaks walking up leftward slopes. + point.X = capLeft + } if has := result.ScanBoundingBox(render.Rect{ X: point.X, @@ -165,12 +171,21 @@ func CollidesWithGrid(d Actor, grid *level.Chunker, target render.Point) (*Colli if result.Top && !ceiling { // This is a newly discovered ceiling. ceiling = true - capHeight = result.TopPoint.Y + capHeight = result.TopPoint.Y + 1 + // TODO: the "+ 1" helps prevent clip thru ceiling, probably. + // Similar to the "+ 1" on the left side, below. } if result.Left && !hitLeft { hitLeft = true - capLeft = result.LeftPoint.X + capLeft = result.LeftPoint.X + 1 + + // TODO: there was a clipping bug where the player could clip + // thru a left wall if they jumped slightly while pressing into + // it. (90 degree angle between floor and left wall). The bug + // does NOT repro on right walls, only left. The "+ 1" added to + // capLeft works around it, BUT breaks walking up leftward slopes + // (walking up rightward slopes still works). } if result.Right && !hitRight { hitRight = true @@ -251,8 +266,8 @@ func (c *Collide) ScanGridLine(p1, p2 render.Point, grid *level.Chunker, side Si // pixel with each side, so the Left and Right edges will check the // left- and right-most point. if side == Top || side == Bottom { - p1.X += 1 - p2.X -= 1 + p1.X++ + p2.X-- } for point := range render.IterLine(p1, p2) {