feat: add Deep Sea alternative hunting area
- Add Deep Sea location to navigation map - Create DeepSeaHuntingScene with dark atmosphere - Add deep ocean transition visuals - Bioluminescent particles and giant shadows Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import ShipDeckScene from './scenes/ShipDeckScene.js';
|
|||||||
import MapScene from './scenes/MapScene.js';
|
import MapScene from './scenes/MapScene.js';
|
||||||
import TransitionScene from './scenes/TransitionScene.js';
|
import TransitionScene from './scenes/TransitionScene.js';
|
||||||
import HuntingScene from './scenes/HuntingScene.js';
|
import HuntingScene from './scenes/HuntingScene.js';
|
||||||
|
import DeepSeaHuntingScene from './scenes/DeepSeaHuntingScene.js';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
type: Phaser.AUTO,
|
type: Phaser.AUTO,
|
||||||
@@ -11,7 +12,7 @@ const config = {
|
|||||||
height: 600,
|
height: 600,
|
||||||
parent: 'game-container',
|
parent: 'game-container',
|
||||||
backgroundColor: '#2d5f8e',
|
backgroundColor: '#2d5f8e',
|
||||||
scene: [IntroScene, ShipDeckScene, MapScene, TransitionScene, HuntingScene],
|
scene: [IntroScene, ShipDeckScene, MapScene, TransitionScene, HuntingScene, DeepSeaHuntingScene],
|
||||||
physics: {
|
physics: {
|
||||||
default: 'arcade',
|
default: 'arcade',
|
||||||
arcade: {
|
arcade: {
|
||||||
|
|||||||
142
src/scenes/DeepSeaHuntingScene.js
Normal file
142
src/scenes/DeepSeaHuntingScene.js
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import Phaser from 'phaser';
|
||||||
|
import { fontSize } from '../utils/responsive.js';
|
||||||
|
import { createFullscreenButton } from '../utils/fullscreen.js';
|
||||||
|
|
||||||
|
export default class DeepSeaHuntingScene extends Phaser.Scene {
|
||||||
|
constructor() {
|
||||||
|
super({ key: 'DeepSeaHuntingScene' });
|
||||||
|
}
|
||||||
|
|
||||||
|
init(data) {
|
||||||
|
this.inventory = data.inventory || { whaleOil: 0, fuel: 100, penguins: 0 };
|
||||||
|
this.whalesHunted = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
// Dark deep ocean background
|
||||||
|
this.add.rectangle(400, 300, 800, 600, 0x0a1a2a);
|
||||||
|
|
||||||
|
// Create atmospheric effects
|
||||||
|
this.createDeepOceanAtmosphere();
|
||||||
|
|
||||||
|
// UI elements
|
||||||
|
this.createHUD();
|
||||||
|
this.createInstructions();
|
||||||
|
|
||||||
|
// Fullscreen button
|
||||||
|
createFullscreenButton(this);
|
||||||
|
|
||||||
|
// Show initial message
|
||||||
|
this.showMessage('Deep Sea Hunting - Coming Soon! Click RETURN to go back.');
|
||||||
|
}
|
||||||
|
|
||||||
|
createDeepOceanAtmosphere() {
|
||||||
|
// Gradient darkness
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
const alpha = 0.05 + i * 0.03;
|
||||||
|
this.add.rectangle(400, 500 - i * 80, 800, 100, 0x000000, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtle waves
|
||||||
|
const graphics = this.add.graphics();
|
||||||
|
graphics.lineStyle(2, 0x1a3a5a, 0.3);
|
||||||
|
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
const y = 80 + i * 70;
|
||||||
|
graphics.beginPath();
|
||||||
|
for (let x = 0; x < 800; x += 30) {
|
||||||
|
const waveY = y + Math.sin((x + i * 50) * 0.012) * 8;
|
||||||
|
if (x === 0) {
|
||||||
|
graphics.moveTo(x, waveY);
|
||||||
|
} else {
|
||||||
|
graphics.lineTo(x, waveY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphics.strokePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bioluminescent particles
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const x = Math.random() * 800;
|
||||||
|
const y = 100 + Math.random() * 400;
|
||||||
|
const particle = this.add.circle(x, y, 2 + Math.random() * 2, 0x4a9fff, 0.5);
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: particle,
|
||||||
|
alpha: { from: 0.5, to: 0.1 },
|
||||||
|
y: y - 30,
|
||||||
|
duration: 3000 + Math.random() * 2000,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Sine.inOut'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Giant shadow placeholder
|
||||||
|
const shadow = this.add.ellipse(400, 350, 250, 100, 0x000000, 0.4);
|
||||||
|
this.tweens.add({
|
||||||
|
targets: shadow,
|
||||||
|
x: 450,
|
||||||
|
y: 370,
|
||||||
|
scaleX: 1.1,
|
||||||
|
scaleY: 0.9,
|
||||||
|
duration: 5000,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Sine.inOut'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createHUD() {
|
||||||
|
// HUD background
|
||||||
|
const hudBg = this.add.rectangle(400, 30, 780, 50, 0x000000, 0.7);
|
||||||
|
hudBg.setStrokeStyle(2, 0x4a9fff);
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
this.statsText = this.add.text(20, 15, '', {
|
||||||
|
fontSize: fontSize(16),
|
||||||
|
fill: '#4a9fff'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return button
|
||||||
|
const returnBtn = this.add.rectangle(750, 30, 80, 35, 0x1a3a5a);
|
||||||
|
returnBtn.setInteractive({ useHandCursor: true });
|
||||||
|
returnBtn.setStrokeStyle(2, 0x4a9fff);
|
||||||
|
|
||||||
|
const returnText = this.add.text(750, 30, 'RETURN', {
|
||||||
|
fontSize: fontSize(14),
|
||||||
|
fill: '#4a9fff'
|
||||||
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
|
returnBtn.on('pointerdown', () => {
|
||||||
|
this.returnToMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStats() {
|
||||||
|
this.statsText.setText([
|
||||||
|
`Fuel: ${this.inventory.fuel}/100`,
|
||||||
|
`Oil: ${this.inventory.whaleOil}/50`,
|
||||||
|
`Leviathans: ${this.whalesHunted}`
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
createInstructions() {
|
||||||
|
this.messageText = this.add.text(400, 570, '', {
|
||||||
|
fontSize: fontSize(16),
|
||||||
|
fill: '#4a9fff',
|
||||||
|
backgroundColor: '#000000',
|
||||||
|
padding: { x: 10, y: 5 }
|
||||||
|
}).setOrigin(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
showMessage(text) {
|
||||||
|
this.messageText.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnToMap() {
|
||||||
|
this.scene.start('MapScene', { inventory: this.inventory });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,6 +46,11 @@ export default class MapScene extends Phaser.Scene {
|
|||||||
'Return to port to resupply fuel and sell whale oil.',
|
'Return to port to resupply fuel and sell whale oil.',
|
||||||
() => this.goToPort());
|
() => this.goToPort());
|
||||||
|
|
||||||
|
// Deep Sea - Alternative hunting area
|
||||||
|
this.createLocation(550, 150, 'DEEP\nSEA', 0x0a2a4a,
|
||||||
|
'Treacherous deep waters. Giant whales lurk in the abyss...',
|
||||||
|
() => this.goToDeepSea());
|
||||||
|
|
||||||
// Inventory display
|
// Inventory display
|
||||||
this.createInventoryDisplay();
|
this.createInventoryDisplay();
|
||||||
|
|
||||||
@@ -212,4 +217,14 @@ export default class MapScene extends Phaser.Scene {
|
|||||||
nextScene: 'MapScene' // Will change to 'PortScene' when implemented
|
nextScene: 'MapScene' // Will change to 'PortScene' when implemented
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToDeepSea() {
|
||||||
|
// Sailing is free - fuel is only for cooking
|
||||||
|
this.scene.start('TransitionScene', {
|
||||||
|
inventory: this.inventory,
|
||||||
|
destination: 'deepsea',
|
||||||
|
fuelCost: 0,
|
||||||
|
nextScene: 'DeepSeaHuntingScene'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,6 +125,12 @@ export default class TransitionScene extends Phaser.Scene {
|
|||||||
description: 'The familiar harbor comes into view. Seagulls circle overhead.\nYou can already smell the taverns and hear the merchants haggling.\nTime to resupply and sell your cargo.',
|
description: 'The familiar harbor comes into view. Seagulls circle overhead.\nYou can already smell the taverns and hear the merchants haggling.\nTime to resupply and sell your cargo.',
|
||||||
backgroundColor: 0x654321,
|
backgroundColor: 0x654321,
|
||||||
visualType: 'harbor'
|
visualType: 'harbor'
|
||||||
|
},
|
||||||
|
'deepsea': {
|
||||||
|
title: 'Descending into the Deep Sea',
|
||||||
|
description: 'The waters grow dark and cold. Your ship ventures into uncharted depths.\nMassive shadows move beneath the surface. The crew whispers of leviathans.\nOnly the bravest—or most foolish—hunt here...',
|
||||||
|
backgroundColor: 0x0a1a2a,
|
||||||
|
visualType: 'deep_ocean'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,6 +153,9 @@ export default class TransitionScene extends Phaser.Scene {
|
|||||||
case 'harbor':
|
case 'harbor':
|
||||||
this.createHarbor();
|
this.createHarbor();
|
||||||
break;
|
break;
|
||||||
|
case 'deep_ocean':
|
||||||
|
this.createDeepOcean();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this.createOcean();
|
this.createOcean();
|
||||||
break;
|
break;
|
||||||
@@ -305,4 +314,74 @@ export default class TransitionScene extends Phaser.Scene {
|
|||||||
graphics.strokePath();
|
graphics.strokePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createDeepOcean() {
|
||||||
|
// Dark, eerie deep ocean atmosphere
|
||||||
|
|
||||||
|
// Gradient effect with darker rectangles
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
const alpha = 0.1 + i * 0.05;
|
||||||
|
this.add.rectangle(400, 50 + i * 50, 800, 50, 0x000000, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtle dark waves
|
||||||
|
const graphics = this.add.graphics();
|
||||||
|
graphics.lineStyle(2, 0x1a3a5a, 0.4);
|
||||||
|
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
const y = 80 + i * 50;
|
||||||
|
graphics.beginPath();
|
||||||
|
for (let x = 0; x < 800; x += 25) {
|
||||||
|
const waveY = y + Math.sin((x + i * 40) * 0.015) * 12;
|
||||||
|
if (x === 0) {
|
||||||
|
graphics.moveTo(x, waveY);
|
||||||
|
} else {
|
||||||
|
graphics.lineTo(x, waveY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphics.strokePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Massive shadows lurking below
|
||||||
|
for (let i = 0; i < 2; i++) {
|
||||||
|
const x = 200 + i * 400;
|
||||||
|
const y = 200 + Math.random() * 80;
|
||||||
|
|
||||||
|
// Giant whale shadow
|
||||||
|
const shadow = this.add.ellipse(x, y, 200, 80, 0x000000, 0.3);
|
||||||
|
|
||||||
|
// Slow, ominous movement
|
||||||
|
this.tweens.add({
|
||||||
|
targets: shadow,
|
||||||
|
x: x + 30,
|
||||||
|
y: y + 15,
|
||||||
|
scaleX: 1.1,
|
||||||
|
duration: 4000,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Sine.inOut'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bioluminescent particles
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
const x = Math.random() * 800;
|
||||||
|
const y = Math.random() * 300;
|
||||||
|
const particle = this.add.circle(x, y, 2, 0x4a9fff, 0.6);
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: particle,
|
||||||
|
alpha: { from: 0.6, to: 0.1 },
|
||||||
|
y: y - 20,
|
||||||
|
duration: 2000 + Math.random() * 2000,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Sine.inOut'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ship silhouette at top
|
||||||
|
this.add.rectangle(100, 60, 70, 35, 0x1a1a1a, 0.8);
|
||||||
|
this.add.polygon(100, 45, [0, 0, -35, 30, 35, 30], 0x2a2a2a, 0.8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user