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, 'The Deck - Yer 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 things to have a look, ye scurvy dog', { fontSize: '16px', fill: '#ffff99' }).setOrigin(0.5); } createDeck() { // Ship deck dimensions this.deckCenterX = 400; this.deckWidth = 700; this.deckTopY = 200; this.deckPlankSpacing = 30; this.deckPlankCount = 8; // Calculate deck boundaries this.deckLeftX = this.deckCenterX - this.deckWidth / 2; this.deckRightX = this.deckCenterX + this.deckWidth / 2; this.deckBottomY = this.deckTopY + (this.deckPlankCount - 1) * this.deckPlankSpacing; // Ship deck planks for (let i = 0; i < this.deckPlankCount; i++) { this.add.rectangle(this.deckCenterX, this.deckTopY + i * this.deckPlankSpacing, this.deckWidth, 25, 0x654321) .setStrokeStyle(2, 0x3d2817); } // Calculate actual deck edges (including plank height) const plankHeight = 25; this.deckTopEdge = this.deckTopY - (plankHeight / 2); this.deckBottomEdge = this.deckBottomY + (plankHeight / 2); const deckHeight = this.deckBottomEdge - this.deckTopEdge; const deckCenterY = (this.deckTopEdge + this.deckBottomEdge) / 2; const deckBorder = this.add.rectangle(this.deckCenterX, deckCenterY, this.deckWidth, deckHeight); deckBorder.setStrokeStyle(4, 0x3d2817); deckBorder.setFillStyle(0x000000, 0); // Transparent fill } createBarrels() { // Initialize barrel arrays this.fuelBarrels = []; this.oilBarrels = []; // Create stacked barrels this.createFuelBarrels(); this.createOilBarrels(); // Penguin cage (hidden until discovered) this.penguinCage = this.add.rectangle(650, 350, 80, 80, 0x333333); this.penguinCage.setInteractive({ useHandCursor: true }); this.penguinCage.setStrokeStyle(3, 0x000000); this.penguinEmoji = this.add.text(650, 350, '🐧', { fontSize: '32px' }).setOrigin(0.5); // Hide penguin elements if not yet discovered const discovered = this.inventory.penguins > 0; this.penguinCage.setVisible(discovered); this.penguinEmoji.setVisible(discovered); this.penguinCage.on('pointerdown', () => { if (this.inventory.penguins > 0) { this.showMessage(`Arr, ${this.inventory.penguins} penguins in the hold. Emergency fuel, they be. Desperate times call fer desperate measures, savvy?`); } else { this.showMessage(`Empty penguin cage, aye. Should we be catchin' some fer... fuel?`); } }); } createFuelBarrels() { const barrelCount = Math.ceil(this.inventory.fuel / 10); if (barrelCount === 0) return; const barrelWidth = 50; const barrelHeight = 70; const horizontalSpacing = 60; const verticalSpacing = 75; const barrelsPerRow = 5; // Calculate group dimensions const groupWidth = (Math.min(barrelCount, barrelsPerRow) * horizontalSpacing); const stackLevels = Math.ceil(barrelCount / barrelsPerRow); // Center horizontally in left half of deck const leftHalfCenter = this.deckLeftX + (this.deckWidth / 4); const baseX = leftHalfCenter - (groupWidth / 2) + (horizontalSpacing / 2); // Center vertically on deck (using actual deck edges) const deckVerticalCenter = (this.deckTopEdge + this.deckBottomEdge) / 2; // Calculate where bottom barrel should be so group is centered // Top of group = baseY - (stackLevels-1)*verticalSpacing - barrelHeight/2 // Bottom of group = baseY + barrelHeight/2 // Center of group = (top + bottom) / 2 = baseY - ((stackLevels-1)*verticalSpacing)/2 // We want: baseY - ((stackLevels-1)*verticalSpacing)/2 = deckVerticalCenter const baseY = deckVerticalCenter + ((stackLevels - 1) * verticalSpacing) / 2; // Create barrels in stacking pattern for (let i = 0; i < barrelCount; i++) { const row = i % barrelsPerRow; const stackLevel = Math.floor(i / barrelsPerRow); const x = baseX + (row * horizontalSpacing); const y = baseY - (stackLevel * verticalSpacing); const barrel = this.add.rectangle(x, y, barrelWidth, barrelHeight, 0x8B0000); barrel.setStrokeStyle(3, 0x000000); this.fuelBarrels.push(barrel); // Add label only on first barrel if (i === 0) { const label = this.add.text(x, y, 'FUEL', { fontSize: '12px', fill: '#fff' }).setOrigin(0.5); this.fuelBarrels.push(label); } } // Create interactive zone covering all fuel barrels const zoneWidth = Math.min(barrelCount, barrelsPerRow) * horizontalSpacing + barrelWidth; const zoneHeight = Math.ceil(barrelCount / barrelsPerRow) * verticalSpacing + barrelHeight; const zoneX = baseX + ((Math.min(barrelCount, barrelsPerRow) - 1) * horizontalSpacing) / 2; const zoneY = baseY - ((Math.ceil(barrelCount / barrelsPerRow) - 1) * verticalSpacing) / 2; const interactiveZone = this.add.rectangle(zoneX, zoneY, zoneWidth, zoneHeight, 0x000000, 0); interactiveZone.setInteractive({ useHandCursor: true }); interactiveZone.on('pointerdown', () => { this.showMessage(`Arr! ${barrelCount} barrels of fuel (${this.inventory.fuel} units) fer boilin' down the blubber, aye!`); }); this.fuelBarrels.push(interactiveZone); } createOilBarrels() { const barrelCount = Math.ceil(this.inventory.whaleOil / 10); if (barrelCount === 0) return; const barrelWidth = 50; const barrelHeight = 70; const horizontalSpacing = 60; const verticalSpacing = 75; const barrelsPerRow = 3; // Calculate group dimensions const groupWidth = (Math.min(barrelCount, barrelsPerRow) * horizontalSpacing); const stackLevels = Math.ceil(barrelCount / barrelsPerRow); // Center horizontally in right half of deck const rightHalfCenter = this.deckCenterX + (this.deckWidth / 4); const baseX = rightHalfCenter - (groupWidth / 2) + (horizontalSpacing / 2); // Center vertically on deck (using actual deck edges) const deckVerticalCenter = (this.deckTopEdge + this.deckBottomEdge) / 2; // Calculate where bottom barrel should be so group is centered const baseY = deckVerticalCenter + ((stackLevels - 1) * verticalSpacing) / 2; // Create barrels in stacking pattern for (let i = 0; i < barrelCount; i++) { const row = i % barrelsPerRow; const stackLevel = Math.floor(i / barrelsPerRow); const x = baseX + (row * horizontalSpacing); const y = baseY - (stackLevel * verticalSpacing); const barrel = this.add.rectangle(x, y, barrelWidth, barrelHeight, 0x4B4B00); barrel.setStrokeStyle(3, 0x000000); this.oilBarrels.push(barrel); // Add label only on first barrel if (i === 0) { const label = this.add.text(x, y, 'OIL', { fontSize: '12px', fill: '#fff' }).setOrigin(0.5); this.oilBarrels.push(label); } } // Create interactive zone covering all oil barrels const zoneWidth = Math.min(barrelCount, barrelsPerRow) * horizontalSpacing + barrelWidth; const zoneHeight = Math.ceil(barrelCount / barrelsPerRow) * verticalSpacing + barrelHeight; const zoneX = baseX + ((Math.min(barrelCount, barrelsPerRow) - 1) * horizontalSpacing) / 2; const zoneY = baseY - ((Math.ceil(barrelCount / barrelsPerRow) - 1) * verticalSpacing) / 2; const interactiveZone = this.add.rectangle(zoneX, zoneY, zoneWidth, zoneHeight, 0x000000, 0); interactiveZone.setInteractive({ useHandCursor: true }); interactiveZone.on('pointerdown', () => { this.showMessage(`Aye! ${barrelCount} barrels of whale oil (${this.inventory.whaleOil} units). Yer precious cargo, worth its weight in gold!`); }); this.oilBarrels.push(interactiveZone); } clearBarrels() { // Destroy all fuel barrels this.fuelBarrels.forEach(barrel => barrel.destroy()); this.fuelBarrels = []; // Destroy all oil barrels this.oilBarrels.forEach(barrel => barrel.destroy()); this.oilBarrels = []; } createWheel() { // Ship's wheel const wheel = this.add.circle(550, 200, 40, 0x8B4513); wheel.setInteractive({ useHandCursor: true }); wheel.setStrokeStyle(4, 0x654321); // Wheel spokes const spokeDebug = this.add.graphics(); spokeDebug.lineStyle(2, 0x0000FF, 0.8); 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); // Debug: Draw blue lines showing spoke endpoints spokeDebug.lineBetween(x1, y1, x2, y2); // Draw circles at endpoints spokeDebug.strokeCircle(x1, y1, 3); spokeDebug.strokeCircle(x2, y2, 3); } wheel.on('pointerdown', () => { // Open the map scene this.scene.start('MapScene', { inventory: this.inventory }); }); // Debug: Draw lines for wheel positioning const debugLines = this.add.graphics(); debugLines.lineStyle(2, 0x00FF00, 0.8); // Center crosshair debugLines.lineBetween(550 - 50, 200, 550 + 50, 200); // Horizontal debugLines.lineBetween(550, 200 - 50, 550, 200 + 50); // Vertical // Bounding box (radius 40) debugLines.strokeRect(550 - 40, 200 - 40, 80, 80); } 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() { const lines = [ 'Inventory:', `Fuel: ${this.inventory.fuel}/100`, `Oil: ${this.inventory.whaleOil}/50` ]; // Only show penguins if discovered (have at least one) const discovered = this.inventory.penguins > 0; if (discovered) { lines.push(`Penguins: ${this.inventory.penguins}/20`); } this.inventoryText.setText(lines); // Update penguin cage visibility if (this.penguinCage) { this.penguinCage.setVisible(discovered); this.penguinEmoji.setVisible(discovered); } // Refresh barrel visualization this.clearBarrels(); this.createFuelBarrels(); this.createOilBarrels(); } 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, 'Ahoy, matey! Welcome aboard. Have a look around the vessel.', { 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(); } } }