feat: Update player sprite to 32x32 with improved animation and collision handling

This commit is contained in:
Kacper Kostka (aider) 2025-04-05 18:22:39 +02:00
parent c853738bbf
commit 84e08b397d
2 changed files with 46 additions and 15 deletions

View File

@ -2,14 +2,14 @@
class Player extends Entity {
constructor(x, y, options = {}) {
super(ENTITY_TYPES.PLAYER, x, y, {
width: 8, // Player size
height: 16,
width: 10, // Adjusted player size to better match 32x32 sprite
height: 20,
...options
});
// Load player sprite
this.sprite = new Image();
this.sprite.src = 'sprites/purplin.png';
this.sprite.src = 'sprites/citizen.png';
// Movement properties
this.moveSpeed = 0.03;
@ -22,6 +22,7 @@ class Player extends Entity {
this.isJumping = false;
this.direction = 1; // 1 = right, -1 = left
this.lastUpdate = performance.now();
this.lastDirection = 1; // Track last direction to prevent unnecessary flipping
// Animation properties
this.frameWidth = 32;
@ -31,6 +32,7 @@ class Player extends Entity {
this.animationSpeed = 150; // ms per frame
this.lastFrameUpdate = 0;
this.isMoving = false;
this.animationTimer = 0; // Consistent timer for animation
}
update() {
@ -87,16 +89,30 @@ class Player extends Entity {
}
updateAnimation(deltaTime) {
// Update animation frame if moving
if (this.isMoving || Math.abs(this.vy) > 0.1) {
this.lastFrameUpdate += deltaTime;
if (this.lastFrameUpdate >= this.animationSpeed) {
// Update animation timer consistently
this.animationTimer += deltaTime;
// Only change animation frame at fixed intervals to prevent blinking
if (this.animationTimer >= this.animationSpeed) {
// Update animation frame if moving
if (this.isMoving || Math.abs(this.vy) > 0.1) {
this.currentFrame = (this.currentFrame + 1) % this.frameCount;
this.lastFrameUpdate = 0;
} else {
// Reset to standing frame when not moving
this.currentFrame = 0;
}
// Reset timer but keep remainder to maintain smooth timing
this.animationTimer %= this.animationSpeed;
}
// Only update direction when it actually changes to prevent flipping
if (this.vx !== 0) {
const newDirection = this.vx > 0 ? 1 : -1;
if (newDirection !== this.lastDirection) {
this.direction = newDirection;
this.lastDirection = newDirection;
}
} else {
// Reset to standing frame when not moving
this.currentFrame = 0;
}
}
@ -108,19 +124,23 @@ class Player extends Entity {
ctx.save();
ctx.translate(screenX, screenY);
// Calculate sprite dimensions - make them proportional to collision box
const spriteWidth = this.width * 1.6 * PIXEL_SIZE; // Wider sprite than collision box
const spriteHeight = this.height * 1.6 * PIXEL_SIZE; // Taller sprite than collision box
// Flip horizontally based on direction
if (this.direction < 0) {
ctx.scale(-1, 1);
ctx.translate(-this.width * PIXEL_SIZE, 0);
}
// Draw the correct sprite frame
// Center the sprite on the entity position, with slight y-offset to align feet
ctx.drawImage(
this.sprite,
this.currentFrame * this.frameWidth, 0,
this.frameWidth, this.frameHeight,
-this.width * PIXEL_SIZE / 2, -this.height * PIXEL_SIZE / 2,
this.width * PIXEL_SIZE, this.height * PIXEL_SIZE
-spriteWidth / 2, -spriteHeight / 2 + 2, // +2 pixel offset to align feet with ground
spriteWidth, spriteHeight
);
ctx.restore();
@ -135,6 +155,16 @@ class Player extends Entity {
this.width * PIXEL_SIZE,
this.height * PIXEL_SIZE
);
// Also draw sprite boundary in debug mode
ctx.strokeStyle = '#ff00ff';
ctx.lineWidth = 1;
ctx.strokeRect(
screenX - spriteWidth / 2,
screenY - spriteHeight / 2 + 2,
spriteWidth,
spriteHeight
);
}
}
}

View File

@ -102,7 +102,8 @@ function spawnPlayer() {
PIXEL_SIZE = 6;
// Create player at specified coordinates
player = createEntity(ENTITY_TYPES.PLAYER, 229, 61);
// Adjust Y position to account for larger sprite size
player = createEntity(ENTITY_TYPES.PLAYER, 229, 55);
// Focus camera on player
worldOffsetX = player.x - (canvas.width / PIXEL_SIZE / 2);