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'; } } }