diff --git a/src/scenes/HuntingScene.js b/src/scenes/HuntingScene.js index 0e8166c..4ef3175 100644 --- a/src/scenes/HuntingScene.js +++ b/src/scenes/HuntingScene.js @@ -9,10 +9,11 @@ export default class HuntingScene extends Phaser.Scene { this.inventory = data.inventory || { whaleOil: 0, fuel: 100, penguins: 0 }; this.whalesHunted = 0; this.harpoons = []; - this.whales = []; + this.currentWhale = null; this.crosshairX = 400; this.crosshairY = 300; this.crosshairSpeed = 5; + this.crosshairShakeAmount = 2; // Pixels of shake this.useKeyboard = false; // Toggle between mouse and keyboard } @@ -26,15 +27,7 @@ export default class HuntingScene extends Phaser.Scene { this.createCrosshair(); this.createInstructions(); - // Spawn whales periodically - this.time.addEvent({ - delay: 3000, - callback: this.spawnWhale, - callbackScope: this, - loop: true - }); - - // Spawn initial whale + // Spawn single whale this.spawnWhale(); // Input setup @@ -52,14 +45,16 @@ export default class HuntingScene extends Phaser.Scene { this.updateCrosshairMouse(); } - // Update crosshair sprite position - this.crosshair.setPosition(this.crosshairX, this.crosshairY); + // Update crosshair sprite position with shake + const shakeX = (Math.random() - 0.5) * this.crosshairShakeAmount * 2; + const shakeY = (Math.random() - 0.5) * this.crosshairShakeAmount * 2; + this.crosshair.setPosition(this.crosshairX + shakeX, this.crosshairY + shakeY); // Update harpoons this.updateHarpoons(); - // Update whales - this.updateWhales(); + // Update whale + this.updateWhale(); // Check collisions this.checkCollisions(); @@ -232,12 +227,17 @@ export default class HuntingScene extends Phaser.Scene { } spawnWhale() { + // Don't spawn if there's already a whale + if (this.currentWhale && this.currentWhale.getData('alive')) { + return; + } + // Random position and direction const fromLeft = Math.random() > 0.5; const x = fromLeft ? -50 : 850; const y = 150 + Math.random() * 300; const direction = fromLeft ? 1 : -1; - const speed = 1 + Math.random() * 1.5; + const speed = 0.8 + Math.random() * 0.7; // Slightly slower for single whale // Create whale body const whale = this.add.container(x, y); @@ -258,39 +258,53 @@ export default class HuntingScene extends Phaser.Scene { 0x1a1a1a ); - whale.add([body, tail, fin]); + // Health bar background + const healthBg = this.add.rectangle(0, -35, 60, 6, 0x000000); + // Health bar (will be updated as whale takes damage) + const healthBar = this.add.rectangle(0, -35, 60, 6, 0x00ff00); + + whale.add([body, tail, fin, healthBg, healthBar]); whale.setData('direction', direction); whale.setData('speed', speed); whale.setData('alive', true); + whale.setData('health', 3); // Requires 3 hits + whale.setData('maxHealth', 3); whale.setData('bodyWidth', 80); whale.setData('bodyHeight', 40); + whale.setData('healthBar', healthBar); // Flip if moving right if (direction > 0) { whale.setScale(-1, 1); } - this.whales.push(whale); + this.currentWhale = whale; } - updateWhales() { - for (let i = this.whales.length - 1; i >= 0; i--) { - const whale = this.whales[i]; + updateWhale() { + if (!this.currentWhale) { + return; + } - if (!whale.getData('alive')) { - continue; - } + const whale = this.currentWhale; - // Move whale - const direction = whale.getData('direction'); - const speed = whale.getData('speed'); - whale.x += direction * speed; + if (!whale.getData('alive')) { + return; + } - // Remove if off screen - if (whale.x < -100 || whale.x > 900) { - whale.destroy(); - this.whales.splice(i, 1); - } + // Move whale + const direction = whale.getData('direction'); + const speed = whale.getData('speed'); + whale.x += direction * speed; + + // If whale goes off screen, spawn a new one + if (whale.x < -100 || whale.x > 900) { + whale.destroy(); + this.currentWhale = null; + // Spawn new whale after a short delay + this.time.delayedCall(1500, () => { + this.spawnWhale(); + }); } } @@ -333,6 +347,12 @@ export default class HuntingScene extends Phaser.Scene { } checkCollisions() { + if (!this.currentWhale || !this.currentWhale.getData('alive')) { + return; + } + + const whale = this.currentWhale; + for (let h = this.harpoons.length - 1; h >= 0; h--) { const harpoon = this.harpoons[h]; @@ -340,31 +360,74 @@ export default class HuntingScene extends Phaser.Scene { continue; } - for (let w = this.whales.length - 1; w >= 0; w--) { - const whale = this.whales[w]; + // Simple collision detection + const distance = Phaser.Math.Distance.Between( + harpoon.x, harpoon.y, + whale.x, whale.y + ); - if (!whale.getData('alive')) { - continue; - } - - // Simple collision detection - const distance = Phaser.Math.Distance.Between( - harpoon.x, harpoon.y, - whale.x, whale.y - ); - - if (distance < 40) { - // Hit! - this.hitWhale(whale, harpoon); - break; - } + if (distance < 40) { + // Hit! + this.hitWhale(whale, harpoon); + break; } } } hitWhale(whale, harpoon) { - whale.setData('alive', false); harpoon.setData('active', false); + harpoon.destroy(); + + // Reduce whale health + let health = whale.getData('health'); + health -= 1; + whale.setData('health', health); + + // Update health bar + const healthBar = whale.getData('healthBar'); + const maxHealth = whale.getData('maxHealth'); + const healthPercent = health / maxHealth; + healthBar.setDisplaySize(60 * healthPercent, 6); + + // Change health bar color based on health + if (healthPercent > 0.6) { + healthBar.setFillStyle(0x00ff00); // Green + } else if (healthPercent > 0.3) { + healthBar.setFillStyle(0xffff00); // Yellow + } else { + healthBar.setFillStyle(0xff0000); // Red + } + + // Hit flash effect + const hitFlash = this.add.circle(whale.x, whale.y, 50, 0xff0000, 0.6); + this.tweens.add({ + targets: hitFlash, + alpha: 0, + scale: 1.5, + duration: 300, + onComplete: () => hitFlash.destroy() + }); + + // Whale damaged animation (shake) + this.tweens.add({ + targets: whale, + x: whale.x + 5, + yoyo: true, + repeat: 2, + duration: 50 + }); + + if (health <= 0) { + // Whale is dead! + this.killWhale(whale); + } else { + // Whale is still alive + this.showMessage(`Hit! Whale health: ${health}/${maxHealth}`); + } + } + + killWhale(whale) { + whale.setData('alive', false); // Check if enough fuel to process the whale if (this.inventory.fuel < 2) { @@ -376,11 +439,15 @@ export default class HuntingScene extends Phaser.Scene { duration: 1000, onComplete: () => { whale.destroy(); + this.currentWhale = null; + // Spawn new whale + this.time.delayedCall(1500, () => { + this.spawnWhale(); + }); } }); - harpoon.destroy(); - this.showMessage('Whale hit but no fuel to process it! Need 2 fuel to cook whale oil.'); + this.showMessage('Whale killed but no fuel to process it! Need 2 fuel to cook whale oil.'); return; } @@ -393,12 +460,14 @@ export default class HuntingScene extends Phaser.Scene { duration: 1000, onComplete: () => { whale.destroy(); + this.currentWhale = null; + // Spawn new whale after delay + this.time.delayedCall(1500, () => { + this.spawnWhale(); + }); } }); - // Remove harpoon - harpoon.destroy(); - // Consume fuel for processing this.inventory.fuel -= 2; @@ -408,7 +477,7 @@ export default class HuntingScene extends Phaser.Scene { this.updateStats(); // Show success message - this.showMessage(`Whale hunted! +1 Whale Oil, -2 Fuel (Oil: ${this.inventory.whaleOil}, Fuel: ${this.inventory.fuel})`); + this.showMessage(`Whale killed! +1 Whale Oil, -2 Fuel (Oil: ${this.inventory.whaleOil}, Fuel: ${this.inventory.fuel})`); // Success flash const flash = this.add.rectangle(400, 300, 800, 600, 0xffffff, 0.3);