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.
This commit is contained in:
parent
d615619aba
commit
695ff4da42
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user