Initial commit: Whale hunting adventure game

- Set up Phaser 3 game framework with Vite
- Created ship deck scene with interactive objects
- Implemented navigation map with destination selection
- Added transition screens for travel between locations
- Inventory system for tracking fuel, whale oil, and penguins
- Three destination types: hunting grounds, Antarctic islands, and port

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Richter
2025-12-15 03:21:05 +01:00
commit 4190170f1f
9 changed files with 1788 additions and 0 deletions

198
src/scenes/MapScene.js Normal file
View File

@@ -0,0 +1,198 @@
import Phaser from 'phaser';
export default class MapScene extends Phaser.Scene {
constructor() {
super({ key: 'MapScene' });
}
init(data) {
// Receive inventory data from previous scene
this.inventory = data.inventory || { whaleOil: 0, fuel: 100, penguins: 0 };
}
create() {
// Ocean background
this.add.rectangle(400, 300, 800, 600, 0x1e5a8e);
// Title
this.add.text(400, 30, 'Navigation Map - Choose Your Destination', {
fontSize: '24px',
fill: '#fff',
fontStyle: 'bold'
}).setOrigin(0.5);
// Draw some decorative waves
this.drawWaves();
// Current position marker (The Ship)
this.createLocation(400, 300, 'SHIP', 0x8B4513,
'Your current position. Click to return to ship deck.',
() => this.returnToShip());
// Hunting Grounds
this.createLocation(250, 200, 'HUNTING\nGROUNDS', 0x2d5f8e,
'Rich waters where whales gather. Dangerous but profitable!',
() => this.goToHunting());
// Antarctic Island (for penguins)
this.createLocation(600, 450, 'ANTARCTIC\nISLAND', 0xE0E0E0,
'Cold, desolate islands inhabited by penguins...',
() => this.goToAntarctic());
// Port
this.createLocation(150, 500, 'PORT', 0x654321,
'Return to port to resupply fuel and sell whale oil.',
() => this.goToPort());
// Inventory display
this.createInventoryDisplay();
// Message box
this.createMessageBox();
this.showMessage('Select a destination. Watch your fuel levels!');
// Close map button
const closeButton = this.add.rectangle(750, 50, 80, 40, 0x8B0000);
closeButton.setInteractive({ useHandCursor: true });
closeButton.setStrokeStyle(2, 0xffffff);
this.add.text(750, 50, 'CLOSE', {
fontSize: '16px',
fill: '#fff'
}).setOrigin(0.5);
closeButton.on('pointerdown', () => {
this.returnToShip();
});
}
drawWaves() {
// Decorative wave lines
const graphics = this.add.graphics();
graphics.lineStyle(2, 0x4a90c4, 0.5);
for (let i = 0; i < 10; i++) {
const y = 100 + i * 50;
graphics.beginPath();
for (let x = 0; x < 800; x += 20) {
const waveY = y + Math.sin((x + i * 30) * 0.02) * 10;
if (x === 0) {
graphics.moveTo(x, waveY);
} else {
graphics.lineTo(x, waveY);
}
}
graphics.strokePath();
}
}
createLocation(x, y, name, color, description, onClick) {
// Location marker
const marker = this.add.circle(x, y, 30, color);
marker.setInteractive({ useHandCursor: true });
marker.setStrokeStyle(3, 0xffffff);
// Location name
const text = this.add.text(x, y, name, {
fontSize: '12px',
fill: '#fff',
fontStyle: 'bold',
align: 'center'
}).setOrigin(0.5);
// Hover effect
marker.on('pointerover', () => {
marker.setScale(1.1);
this.showMessage(description);
});
marker.on('pointerout', () => {
marker.setScale(1);
});
marker.on('pointerdown', onClick);
}
createInventoryDisplay() {
const panel = this.add.rectangle(80, 80, 140, 100, 0x000000, 0.8);
panel.setStrokeStyle(2, 0xffffff);
this.inventoryText = this.add.text(20, 40, '', {
fontSize: '14px',
fill: '#fff'
});
this.updateInventoryDisplay();
}
updateInventoryDisplay() {
this.inventoryText.setText([
'Inventory:',
`Fuel: ${this.inventory.fuel}`,
`Oil: ${this.inventory.whaleOil}`,
`Penguins: ${this.inventory.penguins}`
]);
}
createMessageBox() {
this.messageBox = this.add.rectangle(400, 560, 760, 60, 0x000000, 0.8);
this.messageBox.setStrokeStyle(2, 0xcccccc);
this.messageText = this.add.text(400, 560, '', {
fontSize: '16px',
fill: '#fff',
wordWrap: { width: 740 },
align: 'center'
}).setOrigin(0.5);
}
showMessage(message) {
this.messageText.setText(message);
}
returnToShip() {
this.scene.start('ShipDeckScene', { inventory: this.inventory });
}
goToHunting() {
if (this.inventory.fuel < 20) {
this.showMessage('Not enough fuel to reach the hunting grounds! You need at least 20 units.');
return;
}
// Go to transition scene, then to map (hunting scene not yet implemented)
this.scene.start('TransitionScene', {
inventory: this.inventory,
destination: 'hunting',
fuelCost: 20,
nextScene: 'MapScene' // Will change to 'HuntingScene' when implemented
});
}
goToAntarctic() {
if (this.inventory.fuel < 30) {
this.showMessage('Not enough fuel to reach Antarctic islands! You need at least 30 units.');
return;
}
// Go to transition scene, then to map (antarctic scene not yet implemented)
this.scene.start('TransitionScene', {
inventory: this.inventory,
destination: 'antarctic',
fuelCost: 30,
nextScene: 'MapScene' // Will change to 'AntarcticScene' when implemented
});
}
goToPort() {
if (this.inventory.fuel < 10) {
this.showMessage('Not enough fuel to return to port! You need at least 10 units. Consider... alternatives.');
return;
}
// Go to transition scene, then to map (port scene not yet implemented)
this.scene.start('TransitionScene', {
inventory: this.inventory,
destination: 'port',
fuelCost: 10,
nextScene: 'MapScene' // Will change to 'PortScene' when implemented
});
}
}