From be41f912a2105730b49eac1e391bf2193237779b Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 5 Feb 2026 00:05:03 +0100 Subject: [PATCH] feat: add fullscreen mode toggle button - Add src/utils/fullscreen.js with createFullscreenButton() helper - Fullscreen button appears in bottom-right corner of all scenes - Click to toggle fullscreen mode - Uses Phaser's built-in scale manager Co-Authored-By: Claude Opus 4.5 --- src/scenes/HuntingScene.js | 4 ++ src/scenes/IntroScene.js | 4 ++ src/scenes/MapScene.js | 4 ++ src/scenes/ShipDeckScene.js | 4 ++ src/scenes/TransitionScene.js | 4 ++ src/utils/fullscreen.js | 75 +++++++++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+) create mode 100644 src/utils/fullscreen.js diff --git a/src/scenes/HuntingScene.js b/src/scenes/HuntingScene.js index bbf5f58..d955376 100644 --- a/src/scenes/HuntingScene.js +++ b/src/scenes/HuntingScene.js @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { fontSize } from '../utils/responsive.js'; +import { createFullscreenButton } from '../utils/fullscreen.js'; export default class HuntingScene extends Phaser.Scene { constructor() { @@ -47,6 +48,9 @@ export default class HuntingScene extends Phaser.Scene { // Message display const shootMessage = this.isMobile ? 'Hunt whales! Tap to shoot harpoon.' : 'Hunt whales! Click or press SPACE to shoot harpoon.'; this.showMessage(shootMessage); + + // Fullscreen button (positioned to avoid HUD) + createFullscreenButton(this, { x: 30, y: 580 }); } update() { diff --git a/src/scenes/IntroScene.js b/src/scenes/IntroScene.js index b965435..258575e 100644 --- a/src/scenes/IntroScene.js +++ b/src/scenes/IntroScene.js @@ -1,4 +1,5 @@ import { fontSize } from '../utils/responsive.js'; +import { createFullscreenButton } from '../utils/fullscreen.js'; export default class IntroScene extends Phaser.Scene { constructor() { @@ -78,6 +79,9 @@ export default class IntroScene extends Phaser.Scene { fontSize: fontSize(16), fill: '#ffff99' }).setOrigin(0.5); + + // Fullscreen button + createFullscreenButton(this); } drawWaves() { diff --git a/src/scenes/MapScene.js b/src/scenes/MapScene.js index 92c74da..4e06b3c 100644 --- a/src/scenes/MapScene.js +++ b/src/scenes/MapScene.js @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { fontSize } from '../utils/responsive.js'; +import { createFullscreenButton } from '../utils/fullscreen.js'; export default class MapScene extends Phaser.Scene { constructor() { @@ -73,6 +74,9 @@ export default class MapScene extends Phaser.Scene { closeText.setScale(1.0); this.returnToShip(); }); + + // Fullscreen button + createFullscreenButton(this); } drawWaves() { diff --git a/src/scenes/ShipDeckScene.js b/src/scenes/ShipDeckScene.js index d018da6..b8b3b21 100644 --- a/src/scenes/ShipDeckScene.js +++ b/src/scenes/ShipDeckScene.js @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { fontSize } from '../utils/responsive.js'; +import { createFullscreenButton } from '../utils/fullscreen.js'; export default class ShipDeckScene extends Phaser.Scene { constructor() { @@ -38,6 +39,9 @@ export default class ShipDeckScene extends Phaser.Scene { fontSize: fontSize(16), fill: '#ffff99' }).setOrigin(0.5); + + // Fullscreen button + createFullscreenButton(this); } createDeck() { diff --git a/src/scenes/TransitionScene.js b/src/scenes/TransitionScene.js index a30ac18..0a3aacb 100644 --- a/src/scenes/TransitionScene.js +++ b/src/scenes/TransitionScene.js @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { fontSize } from '../utils/responsive.js'; +import { createFullscreenButton } from '../utils/fullscreen.js'; export default class TransitionScene extends Phaser.Scene { constructor() { @@ -100,6 +101,9 @@ export default class TransitionScene extends Phaser.Scene { // Proceed to next scene this.scene.start(this.nextScene, { inventory: this.inventory }); }); + + // Fullscreen button + createFullscreenButton(this); } getDestinationContent(destination) { diff --git a/src/utils/fullscreen.js b/src/utils/fullscreen.js new file mode 100644 index 0000000..2189de0 --- /dev/null +++ b/src/utils/fullscreen.js @@ -0,0 +1,75 @@ +// Fullscreen toggle utility for Phaser scenes + +import { fontSize } from './responsive.js'; + +/** + * Create a fullscreen toggle button in the corner of the screen + * @param {Phaser.Scene} scene - The Phaser scene to add the button to + * @param {object} options - Optional configuration + * @param {number} options.x - X position (default: 770) + * @param {number} options.y - Y position (default: 580) + */ +export function createFullscreenButton(scene, options = {}) { + const x = options.x || 770; + const y = options.y || 580; + + // Button background + const btn = scene.add.rectangle(x, y, 50, 30, 0x000000, 0.6); + btn.setStrokeStyle(2, 0xffffff); + btn.setInteractive({ useHandCursor: true }); + btn.setScrollFactor(0); + btn.setDepth(1000); + + // Button icon/text + const icon = scene.add.text(x, y, '⛶', { + fontSize: fontSize(18), + fill: '#ffffff' + }).setOrigin(0.5); + icon.setScrollFactor(0); + icon.setDepth(1001); + + // Update icon based on fullscreen state + const updateIcon = () => { + if (scene.scale.isFullscreen) { + icon.setText('⛶'); + } else { + icon.setText('⛶'); + } + }; + + // Toggle fullscreen on click + btn.on('pointerdown', () => { + btn.setFillStyle(0x333333, 0.8); + btn.setScale(0.95); + icon.setScale(0.95); + }); + + btn.on('pointerup', () => { + btn.setFillStyle(0x000000, 0.6); + btn.setScale(1); + icon.setScale(1); + + if (scene.scale.isFullscreen) { + scene.scale.stopFullscreen(); + } else { + scene.scale.startFullscreen(); + } + updateIcon(); + }); + + btn.on('pointerover', () => { + btn.setFillStyle(0x333333, 0.8); + }); + + btn.on('pointerout', () => { + btn.setFillStyle(0x000000, 0.6); + }); + + // Listen for fullscreen changes + scene.scale.on('enterfullscreen', updateIcon); + scene.scale.on('leavefullscreen', updateIcon); + + return { btn, icon }; +} + +export default { createFullscreenButton };