feat: Update player sprite to 32x32 with improved animation and collision handling
This commit is contained in:
parent
c853738bbf
commit
84e08b397d
@ -2,14 +2,14 @@
|
|||||||
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, // Player size
|
width: 10, // Adjusted player size to better match 32x32 sprite
|
||||||
height: 16,
|
height: 20,
|
||||||
...options
|
...options
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load player sprite
|
// Load player sprite
|
||||||
this.sprite = new Image();
|
this.sprite = new Image();
|
||||||
this.sprite.src = 'sprites/purplin.png';
|
this.sprite.src = 'sprites/citizen.png';
|
||||||
|
|
||||||
// Movement properties
|
// Movement properties
|
||||||
this.moveSpeed = 0.03;
|
this.moveSpeed = 0.03;
|
||||||
@ -22,6 +22,7 @@ class Player extends Entity {
|
|||||||
this.isJumping = false;
|
this.isJumping = false;
|
||||||
this.direction = 1; // 1 = right, -1 = left
|
this.direction = 1; // 1 = right, -1 = left
|
||||||
this.lastUpdate = performance.now();
|
this.lastUpdate = performance.now();
|
||||||
|
this.lastDirection = 1; // Track last direction to prevent unnecessary flipping
|
||||||
|
|
||||||
// Animation properties
|
// Animation properties
|
||||||
this.frameWidth = 32;
|
this.frameWidth = 32;
|
||||||
@ -31,6 +32,7 @@ class Player extends Entity {
|
|||||||
this.animationSpeed = 150; // ms per frame
|
this.animationSpeed = 150; // ms per frame
|
||||||
this.lastFrameUpdate = 0;
|
this.lastFrameUpdate = 0;
|
||||||
this.isMoving = false;
|
this.isMoving = false;
|
||||||
|
this.animationTimer = 0; // Consistent timer for animation
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@ -87,16 +89,30 @@ class Player extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateAnimation(deltaTime) {
|
updateAnimation(deltaTime) {
|
||||||
// Update animation frame if moving
|
// Update animation timer consistently
|
||||||
if (this.isMoving || Math.abs(this.vy) > 0.1) {
|
this.animationTimer += deltaTime;
|
||||||
this.lastFrameUpdate += deltaTime;
|
|
||||||
if (this.lastFrameUpdate >= this.animationSpeed) {
|
// 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.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.save();
|
||||||
ctx.translate(screenX, screenY);
|
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
|
// Flip horizontally based on direction
|
||||||
if (this.direction < 0) {
|
if (this.direction < 0) {
|
||||||
ctx.scale(-1, 1);
|
ctx.scale(-1, 1);
|
||||||
ctx.translate(-this.width * PIXEL_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the correct sprite frame
|
// Draw the correct sprite frame
|
||||||
|
// Center the sprite on the entity position, with slight y-offset to align feet
|
||||||
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,
|
||||||
-this.width * PIXEL_SIZE / 2, -this.height * PIXEL_SIZE / 2,
|
-spriteWidth / 2, -spriteHeight / 2 + 2, // +2 pixel offset to align feet with ground
|
||||||
this.width * PIXEL_SIZE, this.height * PIXEL_SIZE
|
spriteWidth, spriteHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
@ -135,6 +155,16 @@ class Player extends Entity {
|
|||||||
this.width * PIXEL_SIZE,
|
this.width * PIXEL_SIZE,
|
||||||
this.height * 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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,8 @@ function spawnPlayer() {
|
|||||||
PIXEL_SIZE = 6;
|
PIXEL_SIZE = 6;
|
||||||
|
|
||||||
// Create player at specified coordinates
|
// 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
|
// Focus camera on player
|
||||||
worldOffsetX = player.x - (canvas.width / PIXEL_SIZE / 2);
|
worldOffsetX = player.x - (canvas.width / PIXEL_SIZE / 2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user