feat: Add hop effect for player when stepping over items and improve visual overlay management

This commit is contained in:
Z. Cliffe Schreuders
2026-02-14 00:44:32 +00:00
parent 40551a2eae
commit 8b97bcdfb1
2 changed files with 166 additions and 79 deletions

View File

@@ -311,6 +311,25 @@ function getAnimationKey(direction) {
}
}
/**
* Map player directions to compass directions for punch animations
* @param {string} direction - Player direction (down, up, left, right, down-left, etc.)
* @returns {string} - Compass direction (south, north, west, east, south-west, etc.)
*/
function mapPlayerDirectionToCompass(direction) {
const directionMap = {
'right': 'east',
'left': 'west',
'up': 'north',
'down': 'south',
'up-right': 'north-east',
'up-left': 'north-west',
'down-right': 'south-east',
'down-left': 'south-west'
};
return directionMap[direction] || 'south';
}
function updateAnimationSpeed(isRunning) {
// Update animation speed based on whether player is running
if (!player || !player.anims) {
@@ -673,9 +692,10 @@ export function updatePlayerMovement() {
if (player.body.velocity.x === 0 && player.body.velocity.y === 0 && player.isMoving) {
player.isMoving = false;
const animDir = getAnimationKey(player.direction);
// Don't interrupt punch animations
// Don't interrupt special animations: punch, death, hit, etc.
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
if (!currentAnim.includes('punch') && !currentAnim.includes('jab') &&
!currentAnim.includes('death') && !currentAnim.includes('taking-punch')) {
player.anims.play(`idle-${animDir}`, true);
}
}
@@ -754,23 +774,23 @@ function updatePlayerKeyboardMovement() {
player.isMoving = false;
const animDir = getAnimationKey(player.direction);
player.anims.stop(); // Stop current animation
// Don't interrupt punch animations
// Don't interrupt special animations: punch, death, hit, etc.
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
if (!currentAnim.includes('punch') && !currentAnim.includes('jab') &&
!currentAnim.includes('death') && !currentAnim.includes('taking-punch')) {
player.anims.play(`idle-${animDir}`, true);
}
}
} else if (isBlocked) {
// Blocked by collision - play idle animation in the direction we're facing
if (player.isMoving) {
player.isMoving = false;
// Blocked by collision - preserve special animations but switch walk to idle
player.isMoving = false;
const currentAnim = player.anims.currentAnim?.key || '';
// Only change animation if it's a walk animation
// Preserve punch, jab, death, taking-punch, etc.
if (currentAnim.includes('walk')) {
const animDir = getAnimationKey(player.direction);
player.anims.stop(); // Stop current animation
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
player.anims.play(`idle-${animDir}`, true);
}
player.anims.play(`idle-${animDir}`, true);
}
} else if (absVX > absVY * 2) {
// Mostly horizontal movement
@@ -784,9 +804,20 @@ function updatePlayerKeyboardMovement() {
player.setFlipX(shouldFlip);
if (!player.isMoving || player.lastDirection !== player.direction) {
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
// If punching, restart punch animation in new direction
if (currentAnim.includes('punch') || currentAnim.includes('jab')) {
const animType = currentAnim.includes('cross-punch') ? 'cross-punch' : 'lead-jab';
const compassDir = mapPlayerDirectionToCompass(player.direction);
const newPunchKey = `${animType}_${compassDir}`;
if (gameRef.anims.exists(newPunchKey)) {
player.anims.play(newPunchKey, true);
console.log(`🥊 Direction changed during punch, restarting: ${newPunchKey}`);
}
} else {
// Normal walk animation
player.anims.play(`walk-${animDir}`, true);
}
player.isMoving = true;
@@ -798,9 +829,20 @@ function updatePlayerKeyboardMovement() {
player.setFlipX(false);
if (!player.isMoving || player.lastDirection !== player.direction) {
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
// If punching, restart punch animation in new direction
if (currentAnim.includes('punch') || currentAnim.includes('jab')) {
const animType = currentAnim.includes('cross-punch') ? 'cross-punch' : 'lead-jab';
const compassDir = mapPlayerDirectionToCompass(player.direction);
const newPunchKey = `${animType}_${compassDir}`;
if (gameRef.anims.exists(newPunchKey)) {
player.anims.play(newPunchKey, true);
console.log(`🥊 Direction changed during punch, restarting: ${newPunchKey}`);
}
} else {
// Normal walk animation
player.anims.play(`walk-${player.direction}`, true);
}
player.isMoving = true;
@@ -822,9 +864,20 @@ function updatePlayerKeyboardMovement() {
player.setFlipX(shouldFlip);
if (!player.isMoving || player.lastDirection !== player.direction) {
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
// If punching, restart punch animation in new direction
if (currentAnim.includes('punch') || currentAnim.includes('jab')) {
const animType = currentAnim.includes('cross-punch') ? 'cross-punch' : 'lead-jab';
const compassDir = mapPlayerDirectionToCompass(player.direction);
const newPunchKey = `${animType}_${compassDir}`;
if (gameRef.anims.exists(newPunchKey)) {
player.anims.play(newPunchKey, true);
console.log(`🥊 Direction changed during punch, restarting: ${newPunchKey}`);
}
} else {
// Normal walk animation
player.anims.play(`walk-${baseDir}`, true);
}
player.isMoving = true;
@@ -840,9 +893,10 @@ function updatePlayerMouseMovement() {
player.isMoving = false;
// Play idle animation based on last direction
// Don't interrupt punch animations
// Don't interrupt special animations: punch, death, hit, etc.
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
if (!currentAnim.includes('punch') && !currentAnim.includes('jab') &&
!currentAnim.includes('death') && !currentAnim.includes('taking-punch')) {
player.anims.play(`idle-${player.direction}`, true);
}
}
@@ -869,9 +923,10 @@ function updatePlayerMouseMovement() {
player.isMoving = false;
const animDir = getAnimationKey(player.direction);
player.anims.stop(); // Stop current animation
// Don't interrupt punch animations
// Don't interrupt special animations: punch, death, hit, etc.
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
if (!currentAnim.includes('punch') && !currentAnim.includes('jab') &&
!currentAnim.includes('death') && !currentAnim.includes('taking-punch')) {
player.anims.play(`idle-${animDir}`, true);
}
}
@@ -918,9 +973,20 @@ function updatePlayerMouseMovement() {
// Play appropriate animation if not already playing
if (!player.isMoving || player.lastDirection !== player.direction) {
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
// If punching, restart punch animation in new direction
if (currentAnim.includes('punch') || currentAnim.includes('jab')) {
const animType = currentAnim.includes('cross-punch') ? 'cross-punch' : 'lead-jab';
const compassDir = mapPlayerDirectionToCompass(player.direction);
const newPunchKey = `${animType}_${compassDir}`;
if (gameRef.anims.exists(newPunchKey)) {
player.anims.play(newPunchKey, true);
console.log(`🥊 Mouse movement: direction changed during punch, restarting: ${newPunchKey}`);
}
} else {
// Normal walk animation
player.anims.play(`walk-${player.direction}`, true);
}
player.isMoving = true;
@@ -931,15 +997,13 @@ function updatePlayerMouseMovement() {
if (player.body.blocked.none === false) {
isMoving = false;
player.body.setVelocity(0, 0);
if (player.isMoving) {
player.isMoving = false;
player.isMoving = false;
// Switch walk animations to idle, but preserve special animations
const currentAnim = player.anims.currentAnim?.key || '';
if (currentAnim.includes('walk')) {
const animDir = getAnimationKey(player.direction);
player.anims.stop(); // Stop current animation
// Don't interrupt punch animations
const currentAnim = player.anims.currentAnim?.key || '';
if (!currentAnim.includes('punch') && !currentAnim.includes('jab')) {
player.anims.play(`idle-${animDir}`, true);
}
player.anims.play(`idle-${animDir}`, true);
}
}
}

View File

@@ -102,57 +102,80 @@ export function createPlayerBumpEffect() {
steppedOverItems.delete(itemId);
}, 2000);
// Replace red tint effect with punch animation (cross-punch or lead-jab)
// Create hop effect when stepping over item
isPlayerBumping = true;
// Map player direction to atlas compass direction
const directionMap = {
'right': 'east',
'left': 'west',
'up': 'north',
'down': 'south',
'up-right': 'north-east',
'up-left': 'north-west',
'down-right': 'south-east',
'down-left': 'south-west'
// Create a visual overlay sprite that follows the player
if (playerVisualOverlay) {
playerVisualOverlay.destroy();
}
playerVisualOverlay = gameRef.add.sprite(player.x, player.y, player.texture.key);
playerVisualOverlay.setFrame(player.frame.name);
playerVisualOverlay.setScale(player.scaleX, player.scaleY);
playerVisualOverlay.setFlipX(player.flipX);
playerVisualOverlay.setFlipY(player.flipY);
playerVisualOverlay.setDepth(player.depth + 1);
playerVisualOverlay.setAlpha(0.8);
// Hide the original player temporarily
player.setAlpha(0);
// Small hop when stepping over items
const hopHeight = -15; // Smaller than spacebar jump
console.log(`🦘 Stepping over item: ${itemId}, creating hop effect`);
// Start the hop animation
if (playerBumpTween) {
playerBumpTween.destroy();
}
playerBumpTween = gameRef.tweens.add({
targets: { hopOffset: 0 },
hopOffset: hopHeight,
duration: 120, // Faster than spacebar jump
ease: 'Power2',
yoyo: true,
onUpdate: (tween) => {
if (playerVisualOverlay && playerVisualOverlay.active) {
playerVisualOverlay.setY(player.y + tween.getValue());
}
},
onComplete: () => {
// Clean up overlay and restore player
if (playerVisualOverlay) {
playerVisualOverlay.destroy();
playerVisualOverlay = null;
}
player.setAlpha(1);
isPlayerBumping = false;
playerBumpTween = null;
}
});
// Make overlay follow player movement during hop
const followPlayer = () => {
if (playerVisualOverlay && playerVisualOverlay.active) {
playerVisualOverlay.setX(player.x);
playerVisualOverlay.setFlipX(player.flipX);
playerVisualOverlay.setFlipY(player.flipY);
}
};
const compassDir = directionMap[player.direction] || 'south';
// Try to play punch/jab animation if available
const crossPunchKey = `cross-punch_${compassDir}`;
const leadJabKey = `lead-jab_${compassDir}`;
// Update overlay position every frame
const followInterval = setInterval(() => {
if (!playerVisualOverlay || !playerVisualOverlay.active) {
clearInterval(followInterval);
return;
}
followPlayer();
}, 16);
let animPlayed = false;
// Try cross-punch animation first
if (gameRef.anims.exists(crossPunchKey)) {
player.anims.play(crossPunchKey, true);
animPlayed = true;
console.log(`🥊 Bump: Playing cross-punch animation: ${crossPunchKey}`);
}
// Fall back to lead-jab animation
else if (gameRef.anims.exists(leadJabKey)) {
player.anims.play(leadJabKey, true);
animPlayed = true;
console.log(`🥊 Bump: Playing lead-jab animation: ${leadJabKey}`);
}
if (animPlayed) {
// Restore to idle after animation completes
player.once('animationcomplete', () => {
const animDir = typeof getAnimationKey === 'function' ? getAnimationKey(player.direction) : player.direction;
player.anims.play(`idle-${animDir}`, true);
isPlayerBumping = false;
});
} else {
// Fallback: flash red tint for 120ms if no animation available
console.log(`⚠️ No punch animations found (tried ${crossPunchKey}, ${leadJabKey}), using red tint fallback`);
player.setTint(0xff4444);
setTimeout(() => {
player.clearTint();
isPlayerBumping = false;
}, 120);
}
// Clean up interval
setTimeout(() => {
clearInterval(followInterval);
}, 220);
}
});
});