feat: Implement climbing system and tree collision avoidance for player
This commit adds: 1. Player climbing mechanism for small steps 2. Collision avoidance with trees (WOOD and LEAF pixels) 3. Enhanced animation states for climbing and jumping 4. Improved player movement and collision detection
This commit is contained in:
parent
bb1e25e753
commit
c5b7f2f224
@ -149,6 +149,20 @@ class Entity {
|
||||
isPixelSolid(x, y) {
|
||||
// Use ceiling for y coordinate to better detect ground below
|
||||
const pixel = getPixel(Math.floor(x), Math.ceil(y));
|
||||
|
||||
// For player entity, don't collide with trees (WOOD and LEAF)
|
||||
if (this.type === ENTITY_TYPES.PLAYER) {
|
||||
return pixel !== EMPTY &&
|
||||
pixel !== WATER &&
|
||||
pixel !== FIRE &&
|
||||
pixel !== SQUARE &&
|
||||
pixel !== CIRCLE &&
|
||||
pixel !== TRIANGLE &&
|
||||
pixel !== WOOD &&
|
||||
pixel !== LEAF;
|
||||
}
|
||||
|
||||
// For other entities, use the original collision detection
|
||||
return pixel !== EMPTY &&
|
||||
pixel !== WATER &&
|
||||
pixel !== FIRE &&
|
||||
|
@ -23,6 +23,7 @@ class Player extends Entity {
|
||||
this.direction = 1; // 1 = right, -1 = left
|
||||
this.lastUpdate = performance.now();
|
||||
this.lastDirection = 1; // Track last direction to prevent unnecessary flipping
|
||||
this.isClimbing = false; // Track climbing state
|
||||
|
||||
// Animation properties
|
||||
this.frameWidth = 32;
|
||||
@ -62,8 +63,15 @@ class Player extends Entity {
|
||||
|
||||
if (collisionResult.collision) {
|
||||
if (collisionResult.horizontal) {
|
||||
newX = this.x;
|
||||
this.vx = 0;
|
||||
// Try to climb up if there's a 1-pixel step
|
||||
if (this.tryClimbing(newX, newY)) {
|
||||
// Successfully climbed, continue with adjusted position
|
||||
newY -= 1; // Move up one pixel to climb
|
||||
} else {
|
||||
// Can't climb, stop horizontal movement
|
||||
newX = this.x;
|
||||
this.vx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (collisionResult.vertical) {
|
||||
@ -89,24 +97,9 @@ class Player extends Entity {
|
||||
}
|
||||
|
||||
updateAnimation(deltaTime) {
|
||||
|
||||
// Update animation timer consistently
|
||||
this.animationTimer += deltaTime;
|
||||
/*
|
||||
// Only change animation frame at fixed intervals to prevent blinking
|
||||
if (this.animationTimer >= this.animationSpeed) {
|
||||
// Only update animation if actually moving horizontally
|
||||
if (Math.abs(this.vx) > 0.005 && this.isMoving) {
|
||||
this.currentFrame = (this.currentFrame + 1) % this.frameCount;
|
||||
} else if (!this.isMoving || Math.abs(this.vx) < 0.005) {
|
||||
// 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 (Math.abs(this.vx) > 0.005) {
|
||||
const newDirection = this.vx > 0 ? 1 : -1;
|
||||
@ -115,6 +108,24 @@ class Player extends Entity {
|
||||
this.lastDirection = newDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// Update animation frame based on climbing state
|
||||
if (this.isClimbing) {
|
||||
// Use a specific frame for climbing
|
||||
this.currentFrame = 1; // Use frame 1 for climbing animation
|
||||
} else if (this.isJumping) {
|
||||
// Use a specific frame for jumping
|
||||
this.currentFrame = 2; // Use frame 2 for jumping animation
|
||||
} else if (Math.abs(this.vx) > 0.01 && this.isMoving) {
|
||||
// Animate walking
|
||||
if (this.animationTimer >= this.animationSpeed) {
|
||||
this.currentFrame = (this.currentFrame + 1) % this.frameCount;
|
||||
this.animationTimer %= this.animationSpeed;
|
||||
}
|
||||
} else {
|
||||
// Standing still
|
||||
this.currentFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
render(ctx, offsetX, offsetY) {
|
||||
@ -215,6 +226,32 @@ class Player extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
// Try to climb up a small step
|
||||
tryClimbing(newX, newY) {
|
||||
const halfWidth = this.width / 2;
|
||||
|
||||
// Check if there's a solid pixel in front of the player
|
||||
const frontX = newX + (this.direction * halfWidth);
|
||||
const frontY = newY;
|
||||
|
||||
// Check if there's a solid pixel at the current level
|
||||
if (this.isPixelSolid(frontX, frontY)) {
|
||||
// Check if there's empty space one pixel above
|
||||
if (!this.isPixelSolid(frontX, frontY - 1) &&
|
||||
!this.isPixelSolid(this.x, this.y - 1)) {
|
||||
|
||||
// Check if there's ground to stand on after climbing
|
||||
if (this.isPixelSolid(frontX, frontY + 1)) {
|
||||
this.isClimbing = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.isClimbing = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
centerCamera() {
|
||||
// Get current camera center in world coordinates
|
||||
const cameraWidth = canvas.width / PIXEL_SIZE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user