From 84e08b397d5b1f989c33bfeac75996936e62d5ab Mon Sep 17 00:00:00 2001 From: "Kacper Kostka (aider)" Date: Sat, 5 Apr 2025 18:22:39 +0200 Subject: [PATCH] feat: Update player sprite to 32x32 with improved animation and collision handling --- js/entities/player.js | 58 ++++++++++++++++++++++++++++++++----------- js/main.js | 3 ++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/js/entities/player.js b/js/entities/player.js index ffe8d29..84892e7 100644 --- a/js/entities/player.js +++ b/js/entities/player.js @@ -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 + ); } } } diff --git a/js/main.js b/js/main.js index bc87ab6..d6c0b2a 100644 --- a/js/main.js +++ b/js/main.js @@ -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);