fix: Align player collision box and sprite rendering precisely

This commit is contained in:
Kacper Kostka (aider) 2025-04-05 18:33:19 +02:00
parent 04295f9f9f
commit 8e2575f6fc
2 changed files with 21 additions and 9 deletions

View File

@ -81,10 +81,13 @@ class Entity {
const numBottomPoints = 5; const numBottomPoints = 5;
let groundCollision = false; let groundCollision = false;
// For player entity, adjust the collision detection to match sprite feet position
const yOffset = this.type === ENTITY_TYPES.PLAYER ? 2 : 0;
for (let i = 0; i < numBottomPoints; i++) { for (let i = 0; i < numBottomPoints; i++) {
const ratio = i / (numBottomPoints - 1); const ratio = i / (numBottomPoints - 1);
const bottomX = newX - halfWidth + (2 * halfWidth * ratio); const bottomX = newX - halfWidth + (2 * halfWidth * ratio);
const bottomY = newY + halfHeight; const bottomY = newY + halfHeight + yOffset;
if (this.isPixelSolid(bottomX, bottomY)) { if (this.isPixelSolid(bottomX, bottomY)) {
groundCollision = true; groundCollision = true;
@ -99,8 +102,11 @@ class Entity {
} }
// Check side points for horizontal collision // Check side points for horizontal collision
const leftMiddle = { x: newX - halfWidth, y: newY }; // For player entity, adjust the collision detection to match sprite position
const rightMiddle = { x: newX + halfWidth, y: newY }; const yAdjust = this.type === ENTITY_TYPES.PLAYER ? -1 : 0;
const leftMiddle = { x: newX - halfWidth, y: newY + yAdjust };
const rightMiddle = { x: newX + halfWidth, y: newY + yAdjust };
if (this.isPixelSolid(leftMiddle.x, leftMiddle.y)) { if (this.isPixelSolid(leftMiddle.x, leftMiddle.y)) {
result.collision = true; result.collision = true;
@ -113,7 +119,7 @@ class Entity {
} }
// Check top for ceiling collision // Check top for ceiling collision
const topMiddle = { x: newX, y: newY - halfHeight }; const topMiddle = { x: newX, y: newY - halfHeight + (this.type === ENTITY_TYPES.PLAYER ? -2 : 0) };
if (this.isPixelSolid(topMiddle.x, topMiddle.y)) { if (this.isPixelSolid(topMiddle.x, topMiddle.y)) {
result.collision = true; result.collision = true;
result.vertical = true; result.vertical = true;

View File

@ -2,8 +2,8 @@
class Player extends Entity { class Player extends Entity {
constructor(x, y, options = {}) { constructor(x, y, options = {}) {
super(ENTITY_TYPES.PLAYER, x, y, { super(ENTITY_TYPES.PLAYER, x, y, {
width: 8, // Adjusted collision box size width: 6, // Narrower collision box to match sprite
height: 16, height: 12, // Shorter collision box to match sprite
...options ...options
}); });
@ -138,12 +138,12 @@ class Player extends Entity {
} }
// Draw the correct sprite frame // Draw the correct sprite frame
// Center the sprite on the entity position, with slight y-offset to align feet // Center the sprite on the entity position, with y-offset to align feet with collision box
ctx.drawImage( ctx.drawImage(
this.sprite, this.sprite,
this.currentFrame * this.frameWidth, 0, this.currentFrame * this.frameWidth, 0,
this.frameWidth, this.frameHeight, this.frameWidth, this.frameHeight,
-spriteDisplayWidth / 2, -spriteDisplayHeight / 2 + 2, // Reduced offset for smaller sprite -spriteDisplayWidth / 2, -spriteDisplayHeight / 2 - 2, // Adjusted y-offset to align with collision box
spriteDisplayWidth, spriteDisplayHeight spriteDisplayWidth, spriteDisplayHeight
); );
@ -167,10 +167,16 @@ class Player extends Entity {
ctx.lineWidth = 1; ctx.lineWidth = 1;
ctx.strokeRect( ctx.strokeRect(
screenX - spriteDisplayWidth / 2, screenX - spriteDisplayWidth / 2,
screenY - spriteDisplayHeight / 2 + 4, screenY - spriteDisplayHeight / 2 - 2, // Match the sprite drawing offset
spriteDisplayWidth, spriteDisplayWidth,
spriteDisplayHeight spriteDisplayHeight
); );
// Draw a dot at the entity's exact position
ctx.fillStyle = '#ffff00';
ctx.beginPath();
ctx.arc(screenX, screenY, 2, 0, Math.PI * 2);
ctx.fill();
} }
} }
} }