From 4190170f1f1c5933c2a1d1a09114ea433c6bef72 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Mon, 15 Dec 2025 03:21:05 +0100 Subject: [PATCH] Initial commit: Whale hunting adventure game MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .gitignore | 25 + README.md | 84 +++ index.html | 27 + package-lock.json | 961 ++++++++++++++++++++++++++++++++++ package.json | 20 + src/main.js | 26 + src/scenes/MapScene.js | 198 +++++++ src/scenes/ShipDeckScene.js | 165 ++++++ src/scenes/TransitionScene.js | 282 ++++++++++ 9 files changed, 1788 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/main.js create mode 100644 src/scenes/MapScene.js create mode 100644 src/scenes/ShipDeckScene.js create mode 100644 src/scenes/TransitionScene.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..632c90c --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Dependencies +node_modules/ + +# Build output +dist/ + +# Environment variables +.env +.env.local + +# Editor directories +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# Logs +*.log +npm-debug.log* + +# Temporary files +*.tmp +.cache/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..11ae4c1 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# Whale Hunting - A Point & Click Adventure + +A Monkey Island-style adventure game based on 18th century whaling history, including the dark practice of burning penguins as emergency fuel when traditional fuel ran out. + +## Setup + +### Install Dependencies + +```bash +npm install +``` + +### Run Development Server + +```bash +npm run dev +``` + +The game will be available at `http://localhost:5173` (or another port shown in the terminal). + +### Build for Production + +```bash +npm run build +``` + +The built files will be in the `dist/` directory. + +## Project Structure + +``` +whalehunting/ +├── index.html # Main HTML file +├── package.json # Dependencies and scripts +├── src/ +│ ├── main.js # Game initialization and configuration +│ ├── scenes/ # Game scenes +│ │ └── ShipDeckScene.js # Ship deck scene (starting point) +│ └── game-objects/ # Reusable game objects (future) +└── assets/ # Images, sounds, etc. (future) +``` + +## Current Features + +- **Ship Deck Scene**: Explore the deck of your whaling vessel +- **Interactive Objects**: Click on barrels, the ship's wheel, and other objects +- **Inventory System**: Track fuel, whale oil, and penguins +- **Message System**: Get feedback when interacting with objects + +## Game Concept + +The game simulates 18th century whaling expeditions where: +- Whalers hunt whales to produce whale oil +- Fuel management is critical for the voyage +- When fuel runs out, desperate measures (burning penguins) become necessary + +## Next Steps + +Future development could include: +- Whale hunting mini-game/scene +- Port scene for resupply and selling oil +- Decision system for fuel management +- Narrative elements and character dialogues +- Penguin catching mechanics +- Multiple voyages with progression +- Art assets to replace placeholder graphics + +## Technology + +- **Phaser 3**: Game framework +- **Vite**: Build tool and dev server +- **JavaScript (ES6 modules)**: Programming language + +## Controls + +- **Mouse**: Click to interact with objects +- Point-and-click adventure style navigation + +## Development Notes + +This is a prototype with placeholder graphics (colored rectangles). Art assets can be added later by: +1. Adding images to `assets/sprites/` or `assets/backgrounds/` +2. Loading them in the scene's `preload()` method +3. Replacing rectangle shapes with sprites diff --git a/index.html b/index.html new file mode 100644 index 0000000..1b8064a --- /dev/null +++ b/index.html @@ -0,0 +1,27 @@ + + + + + + Whale Hunting - A Point & Click Adventure + + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..23d292e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,961 @@ +{ + "name": "whalehunting-game", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "whalehunting-game", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "phaser": "^3.80.1" + }, + "devDependencies": { + "vite": "^5.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/phaser": { + "version": "3.90.0", + "resolved": "https://registry.npmjs.org/phaser/-/phaser-3.90.0.tgz", + "integrity": "sha512-/cziz/5ZIn02uDkC9RzN8VF9x3Gs3XdFFf9nkiMEQT3p7hQlWuyjy4QWosU802qqno2YSLn2BfqwOKLv/sSVfQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1f0987f --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "whalehunting-game", + "version": "1.0.0", + "description": "A Monkey Island-style point-and-click adventure game about 18th century whaling", + "main": "src/main.js", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "keywords": ["game", "phaser", "adventure", "point-and-click"], + "author": "", + "license": "MIT", + "dependencies": { + "phaser": "^3.80.1" + }, + "devDependencies": { + "vite": "^5.0.0" + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..83a93f6 --- /dev/null +++ b/src/main.js @@ -0,0 +1,26 @@ +import Phaser from 'phaser'; +import ShipDeckScene from './scenes/ShipDeckScene.js'; +import MapScene from './scenes/MapScene.js'; +import TransitionScene from './scenes/TransitionScene.js'; + +const config = { + type: Phaser.AUTO, + width: 800, + height: 600, + parent: 'game-container', + backgroundColor: '#2d5f8e', + scene: [ShipDeckScene, MapScene, TransitionScene], + physics: { + default: 'arcade', + arcade: { + gravity: { y: 0 }, + debug: false + } + }, + scale: { + mode: Phaser.Scale.FIT, + autoCenter: Phaser.Scale.CENTER_BOTH + } +}; + +const game = new Phaser.Game(config); diff --git a/src/scenes/MapScene.js b/src/scenes/MapScene.js new file mode 100644 index 0000000..763ea59 --- /dev/null +++ b/src/scenes/MapScene.js @@ -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 + }); + } +} diff --git a/src/scenes/ShipDeckScene.js b/src/scenes/ShipDeckScene.js new file mode 100644 index 0000000..7998602 --- /dev/null +++ b/src/scenes/ShipDeckScene.js @@ -0,0 +1,165 @@ +import Phaser from 'phaser'; + +export default class ShipDeckScene extends Phaser.Scene { + constructor() { + super({ key: 'ShipDeckScene' }); + this.inventory = { + whaleOil: 0, + fuel: 100, + penguins: 0 + }; + } + + init(data) { + // Receive inventory data when returning from other scenes + if (data && data.inventory) { + this.inventory = data.inventory; + } + } + + create() { + // Background - ship deck + this.add.rectangle(400, 300, 800, 600, 0x8B4513); + this.add.text(400, 30, 'Ship Deck - The Whaling Vessel', { + fontSize: '24px', + fill: '#fff' + }).setOrigin(0.5); + + // Create interactive areas + this.createDeck(); + this.createBarrels(); + this.createWheel(); + this.createInventoryDisplay(); + this.createMessageBox(); + + // Instructions + this.add.text(400, 560, 'Click on objects to interact', { + fontSize: '16px', + fill: '#ffff99' + }).setOrigin(0.5); + } + + createDeck() { + // Ship deck planks + for (let i = 0; i < 8; i++) { + this.add.rectangle(400, 200 + i * 30, 700, 25, 0x654321) + .setStrokeStyle(2, 0x3d2817); + } + } + + createBarrels() { + // Fuel barrel + const fuelBarrel = this.add.rectangle(150, 350, 60, 80, 0x8B0000); + fuelBarrel.setInteractive({ useHandCursor: true }); + fuelBarrel.setStrokeStyle(3, 0x000000); + + this.add.text(150, 350, 'FUEL', { + fontSize: '12px', + fill: '#fff' + }).setOrigin(0.5); + + fuelBarrel.on('pointerdown', () => { + this.showMessage(`Fuel barrel: ${this.inventory.fuel} units remaining. This keeps the ship running.`); + }); + + // Whale oil barrel + const oilBarrel = this.add.rectangle(250, 350, 60, 80, 0x4B4B00); + oilBarrel.setInteractive({ useHandCursor: true }); + oilBarrel.setStrokeStyle(3, 0x000000); + + this.add.text(250, 350, 'OIL', { + fontSize: '12px', + fill: '#fff' + }).setOrigin(0.5); + + oilBarrel.on('pointerdown', () => { + this.showMessage(`Whale oil: ${this.inventory.whaleOil} barrels. Your precious cargo!`); + }); + + // Penguin cage (dark humor ahead) + const penguinCage = this.add.rectangle(650, 350, 80, 80, 0x333333); + penguinCage.setInteractive({ useHandCursor: true }); + penguinCage.setStrokeStyle(3, 0x000000); + + this.add.text(650, 350, '🐧', { + fontSize: '32px' + }).setOrigin(0.5); + + penguinCage.on('pointerdown', () => { + if (this.inventory.penguins > 0) { + this.showMessage(`${this.inventory.penguins} penguins. They're... emergency fuel. Dark times call for dark measures.`); + } else { + this.showMessage('Empty penguin cage. Should we catch some for... fuel?'); + } + }); + } + + createWheel() { + // Ship's wheel + const wheel = this.add.circle(550, 200, 40, 0x8B4513); + wheel.setInteractive({ useHandCursor: true }); + wheel.setStrokeStyle(4, 0x654321); + + // Wheel spokes + for (let i = 0; i < 8; i++) { + const angle = (i * 45) * Math.PI / 180; + const x1 = 550 + Math.cos(angle) * 15; + const y1 = 200 + Math.sin(angle) * 15; + const x2 = 550 + Math.cos(angle) * 35; + const y2 = 200 + Math.sin(angle) * 35; + this.add.line(0, 0, x1, y1, x2, y2, 0x654321).setLineWidth(3); + } + + wheel.on('pointerdown', () => { + // Open the map scene + this.scene.start('MapScene', { inventory: this.inventory }); + }); + } + + createInventoryDisplay() { + // Inventory panel + const panel = this.add.rectangle(80, 80, 140, 100, 0x000000, 0.7); + 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() { + // Message display area + this.messageBox = this.add.rectangle(400, 500, 760, 80, 0x000000, 0.8); + this.messageBox.setStrokeStyle(2, 0xcccccc); + + this.messageText = this.add.text(400, 500, 'Welcome aboard! Click around to explore the ship.', { + fontSize: '16px', + fill: '#fff', + wordWrap: { width: 740 }, + align: 'center' + }).setOrigin(0.5); + } + + showMessage(message) { + this.messageText.setText(message); + } + + // Helper method to modify inventory (for future use) + addToInventory(item, amount) { + if (this.inventory.hasOwnProperty(item)) { + this.inventory[item] += amount; + this.updateInventoryDisplay(); + } + } +} diff --git a/src/scenes/TransitionScene.js b/src/scenes/TransitionScene.js new file mode 100644 index 0000000..53cd35e --- /dev/null +++ b/src/scenes/TransitionScene.js @@ -0,0 +1,282 @@ +import Phaser from 'phaser'; + +export default class TransitionScene extends Phaser.Scene { + constructor() { + super({ key: 'TransitionScene' }); + } + + init(data) { + // Receive data about the destination + this.inventory = data.inventory || { whaleOil: 0, fuel: 100, penguins: 0 }; + this.destination = data.destination || 'unknown'; + this.fuelCost = data.fuelCost || 0; + this.returnScene = data.returnScene || 'MapScene'; + this.nextScene = data.nextScene || 'MapScene'; + } + + create() { + // Get destination-specific content + const content = this.getDestinationContent(this.destination); + + // Background based on destination + this.add.rectangle(400, 300, 800, 600, content.backgroundColor); + + // Add destination-specific visual elements + this.createDestinationVisuals(this.destination, content); + + // Journey text container + const textBox = this.add.rectangle(400, 450, 700, 200, 0x000000, 0.85); + textBox.setStrokeStyle(3, 0xffffff); + + // Destination title + this.add.text(400, 360, content.title, { + fontSize: '32px', + fill: '#ffffff', + fontStyle: 'bold', + stroke: '#000000', + strokeThickness: 4 + }).setOrigin(0.5); + + // Journey description + this.add.text(400, 430, content.description, { + fontSize: '18px', + fill: '#ffffff', + align: 'center', + wordWrap: { width: 660 } + }).setOrigin(0.5); + + // Fuel cost display + this.add.text(400, 500, `Fuel consumed: ${this.fuelCost} units`, { + fontSize: '16px', + fill: '#ffff00' + }).setOrigin(0.5); + + // Continue button + const continueBtn = this.add.rectangle(400, 540, 200, 50, 0x2d5f8e); + continueBtn.setInteractive({ useHandCursor: true }); + continueBtn.setStrokeStyle(3, 0xffffff); + + const btnText = this.add.text(400, 540, 'CONTINUE', { + fontSize: '20px', + fill: '#fff', + fontStyle: 'bold' + }).setOrigin(0.5); + + // Hover effect + continueBtn.on('pointerover', () => { + continueBtn.setFillStyle(0x4a90c4); + }); + + continueBtn.on('pointerout', () => { + continueBtn.setFillStyle(0x2d5f8e); + }); + + continueBtn.on('pointerdown', () => { + // Deduct fuel + this.inventory.fuel -= this.fuelCost; + + // Proceed to next scene + this.scene.start(this.nextScene, { inventory: this.inventory }); + }); + } + + getDestinationContent(destination) { + const destinations = { + 'hunting': { + title: 'Approaching the Hunting Grounds', + description: 'Your vessel cuts through the icy waters. The crew prepares the harpoons.\nIn the distance, spouts of water mark the presence of whales.\nThe hunt is about to begin...', + backgroundColor: 0x1e3a5f, + visualType: 'ocean_whales' + }, + 'antarctic': { + title: 'Arriving at Antarctic Island', + description: 'The ship navigates through floating ice. A desolate, frozen island emerges.\nThousands of penguins waddle along the rocky shores.\nYour crew exchanges uneasy glances. They know why you\'re here...', + backgroundColor: 0x4a5f7f, + visualType: 'ice_penguins' + }, + 'port': { + title: 'Returning to Port', + 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, + visualType: 'harbor' + } + }; + + return destinations[destination] || { + title: 'Traveling...', + description: 'Your journey continues across the vast ocean.', + backgroundColor: 0x2d5f8e, + visualType: 'ocean' + }; + } + + createDestinationVisuals(destination, content) { + switch (content.visualType) { + case 'ocean_whales': + this.createOceanWithWhales(); + break; + case 'ice_penguins': + this.createIceWithPenguins(); + break; + case 'harbor': + this.createHarbor(); + break; + default: + this.createOcean(); + break; + } + } + + createOceanWithWhales() { + // Ocean waves + this.createOcean(); + + // Whale spouts in the distance + for (let i = 0; i < 3; i++) { + const x = 150 + i * 250; + const y = 150 + Math.random() * 100; + + // Whale body (barely visible) + this.add.ellipse(x, y + 20, 60, 30, 0x2a2a2a, 0.6); + + // Water spout + const spout = this.add.triangle( + x, y, + 0, 0, + -8, -30, + 8, -30, + 0x87CEEB, 0.7 + ); + + // Animate spout + this.tweens.add({ + targets: spout, + alpha: { from: 0.7, to: 0.2 }, + y: y - 10, + duration: 1000, + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + } + + // Ship silhouette + this.add.rectangle(700, 280, 80, 40, 0x654321); + this.add.polygon(700, 260, [0, 0, -40, 40, 40, 40], 0x8B4513); + } + + createIceWithPenguins() { + // Icy background effects + for (let i = 0; i < 20; i++) { + const x = Math.random() * 800; + const y = Math.random() * 300; + const size = 5 + Math.random() * 10; + this.add.circle(x, y, size, 0xE0E0E0, 0.3); + } + + // Ice floes + this.add.ellipse(200, 250, 150, 80, 0xF0F0F0); + this.add.ellipse(500, 200, 120, 70, 0xE8E8E8); + this.add.ellipse(650, 270, 100, 60, 0xF5F5F5); + + // Penguins on ice floes + const penguinPositions = [ + {x: 180, y: 240}, {x: 200, y: 245}, {x: 220, y: 238}, + {x: 490, y: 195}, {x: 510, y: 200}, + {x: 645, y: 265} + ]; + + penguinPositions.forEach(pos => { + // Penguin body + this.add.ellipse(pos.x, pos.y, 12, 18, 0x000000); + this.add.ellipse(pos.x, pos.y + 2, 8, 12, 0xFFFFFF); + // Penguin eyes + this.add.circle(pos.x - 2, pos.y - 4, 1.5, 0xFFFFFF); + this.add.circle(pos.x + 2, pos.y - 4, 1.5, 0xFFFFFF); + }); + + // Ship in the background + this.add.rectangle(100, 100, 60, 30, 0x654321, 0.7); + this.add.polygon(100, 85, [0, 0, -30, 30, 30, 30], 0x8B4513, 0.7); + } + + createHarbor() { + // Harbor water + this.add.rectangle(400, 400, 800, 400, 0x2d5f8e); + + // Dock + this.add.rectangle(400, 320, 700, 60, 0x654321); + for (let i = 0; i < 10; i++) { + this.add.rectangle(100 + i * 70, 320, 50, 55, 0x4a3621); + } + + // Buildings in background + const buildings = [ + {x: 100, y: 180, w: 80, h: 120, color: 0x8B4513}, + {x: 220, y: 200, w: 100, h: 100, color: 0x654321}, + {x: 360, y: 170, w: 90, h: 130, color: 0x8B6914}, + {x: 490, y: 190, w: 110, h: 110, color: 0x654321}, + {x: 640, y: 180, w: 95, h: 120, color: 0x8B4513} + ]; + + buildings.forEach(b => { + this.add.rectangle(b.x, b.y, b.w, b.h, b.color); + this.add.rectangle(b.x, b.y, b.w, b.h).setStrokeStyle(2, 0x000000); + // Windows + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 2; j++) { + this.add.rectangle( + b.x - b.w/4 + j * b.w/2, + b.y - b.h/3 + i * b.h/3, + 10, 12, 0xFFDD44 + ); + } + } + }); + + // Barrels on dock + for (let i = 0; i < 5; i++) { + this.add.circle(150 + i * 120, 310, 15, 0x8B0000); + } + + // Seagulls + for (let i = 0; i < 3; i++) { + const x = 200 + i * 200; + const y = 80 + Math.random() * 40; + const bird = this.add.text(x, y, 'v', { + fontSize: '20px', + fill: '#ffffff' + }); + + this.tweens.add({ + targets: bird, + x: x + 50, + y: y - 20, + duration: 2000 + Math.random() * 1000, + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + } + } + + createOcean() { + // Simple ocean waves + const graphics = this.add.graphics(); + graphics.lineStyle(3, 0x4a90c4, 0.7); + + for (let i = 0; i < 8; i++) { + const y = 100 + i * 40; + graphics.beginPath(); + for (let x = 0; x < 800; x += 20) { + const waveY = y + Math.sin((x + i * 30) * 0.03) * 15; + if (x === 0) { + graphics.moveTo(x, waveY); + } else { + graphics.lineTo(x, waveY); + } + } + graphics.strokePath(); + } + } +}