You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.8 KiB
55 lines
1.8 KiB
export class PhysicsSystems { |
|
resolveCollisions(player, platforms, groundY) { |
|
const totalHeight = 60; |
|
const halfFootW = 12; |
|
const EPS = 0.5; |
|
|
|
const feetLeft = player.x - halfFootW; |
|
const feetRight = player.x + halfFootW; |
|
|
|
const prevFeetY = (player._prevY ?? player.y) + totalHeight; |
|
const currFeetY = player.y + totalHeight; |
|
|
|
let landedOnPlatform = false; |
|
|
|
let landed = false; |
|
|
|
// one-way platforms (land only when falling and crossing from above) |
|
if (player.vy >= 0) { |
|
for (const pf of platforms) { |
|
const pfTop = pf.y; |
|
const pfLeft = pf.x; |
|
const pfRight = pf.x + pf.w |
|
|
|
const horizOverlap = feetRight > pfLeft && feetLeft < pfRight; |
|
const crossedTop = (prevFeetY <= pfTop + EPS) && (currFeetY >= pfTop - EPS); |
|
const dropping = player.crouching === true; |
|
|
|
if (horizOverlap && crossedTop && !dropping) { |
|
player.y = pfTop - totalHeight; |
|
player.vy = 0; |
|
player.onGround = true; |
|
landed = true; |
|
player.state = 'ground'; |
|
break; |
|
} |
|
} |
|
} |
|
// --- ground after platforms --- |
|
if (!landedOnPlatform) { |
|
const crossedGround = (prevFeetY <= groundY + EPS) && (currFeetY >= groundY - EPS); |
|
if (crossedGround) { |
|
player.y = groundY - totalHeight; |
|
player.vy = 0; |
|
player.onGround = true; |
|
player.state = 'ground'; |
|
landed = true |
|
} |
|
} |
|
|
|
if (!landed) { |
|
player.onGround = false; |
|
player.state = 'air'; |
|
} |
|
} |
|
}
|
|
|