Skip to content

Commit b86d099

Browse files
committed
Add mute functionality and background music
1 parent 570cdc1 commit b86d099

3 files changed

Lines changed: 81 additions & 4 deletions

File tree

assets/keyboard-m-key-logo.png

442 KB
Loading

assets/pvz-graze-the-roof-128k.mp3

4.47 MB
Binary file not shown.

index.js

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ class PacManScene extends Phaser.Scene {
77
const arrowDistance = this.currentScale * 80; // Distance from Pacman center
88
const keyScale = this.currentScale * 0.065; // Scale for key icons
99

10-
// Create arrows and keys for each direction
10+
// Create arrows and keys for each direction (M sits to the right of D, same spacing as A–D)
1111
const directions = [
1212
{ icon: 'w-key-logo', angle: 0, x: 0, y: -arrowDistance/2, direction: 'up' },
1313
{ icon: 's-key-logo', angle: 0, x: 0, y: arrowDistance/2, direction: 'down' },
1414
{ icon: 'a-key-logo', angle: 0, x: -arrowDistance/2, y: 0, direction: 'left' },
15-
{ icon: 'd-key-logo', angle: 0, x: arrowDistance/2, y: 0, direction: 'right' }
15+
{ icon: 'd-key-logo', angle: 0, x: arrowDistance/2, y: 0, direction: 'right' },
16+
{ icon: 'm-key-logo', angle: 0, x: arrowDistance/2 + arrowDistance, y: 0, direction: 'mute', showCaption: true }
1617
];
1718

1819
this.instructionArrows = [];
20+
this.instructionMuteCaption = null;
1921

2022
directions.forEach(dir => {
2123
// Calculate bounding box size based on key icon dimensions
@@ -46,7 +48,19 @@ class PacManScene extends Phaser.Scene {
4648

4749
// Create container for this direction's elements
4850
const directionContainer = this.add.container(dir.x, dir.y);
49-
directionContainer.add([boundingBox, keyIcon]); // Box first (behind), then icon
51+
const containerChildren = [boundingBox, keyIcon];
52+
53+
if (dir.showCaption) {
54+
const caption = this.add.text(boxWidth/2 + 50, 0, "mute / unmute", {
55+
fontSize: `${Math.floor(10 * Math.max(0.55, this.currentScale))}px`,
56+
fill: '#ffffff',
57+
fontFamily: 'Monaco'
58+
}).setOrigin(0.5);
59+
this.instructionMuteCaption = caption;
60+
containerChildren.push(caption);
61+
}
62+
63+
directionContainer.add(containerChildren);
5064

5165
// Store references
5266
this.instructionArrows.push({
@@ -2238,6 +2252,53 @@ class PacManScene extends Phaser.Scene {
22382252
if (this.pacman && this.pacmanInitialized) {
22392253
this.setupCamera();
22402254
}
2255+
2256+
}
2257+
2258+
setupBackgroundMusicAndMute() {
2259+
if (!this.cache.audio.exists('bgm')) return;
2260+
2261+
this.bgmSound = this.sound.add('bgm', { loop: true, volume: 0.35 });
2262+
2263+
const tryPlayBgm = () => {
2264+
if (!this.bgmSound) return;
2265+
if (!this.bgmSound.isPlaying) {
2266+
this.bgmSound.play();
2267+
}
2268+
};
2269+
2270+
tryPlayBgm();
2271+
this.input.once('pointerdown', tryPlayBgm);
2272+
this.bgmSound.once('play', this.onBgmStartedPlaying, this);
2273+
2274+
this.muteKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.M);
2275+
this.muteKey.on('down', this.toggleMusicMute, this);
2276+
}
2277+
2278+
onBgmStartedPlaying() {
2279+
this.bgmCaptionDynamicReady = true;
2280+
this.updateMusicHintVisual();
2281+
}
2282+
2283+
toggleMusicMute() {
2284+
this.sound.mute = !this.sound.mute;
2285+
this.updateMusicHintVisual();
2286+
}
2287+
2288+
updateMusicHintVisual() {
2289+
if (!this.instructionMuteCaption) return;
2290+
if (!this.bgmCaptionDynamicReady) {
2291+
this.instructionMuteCaption.setText('mute / unmute');
2292+
this.instructionMuteCaption.setColor('#ffffff');
2293+
return;
2294+
}
2295+
if (this.sound.mute) {
2296+
this.instructionMuteCaption.setText('unmute');
2297+
this.instructionMuteCaption.setColor('#ff8888');
2298+
} else {
2299+
this.instructionMuteCaption.setText('mute');
2300+
this.instructionMuteCaption.setColor('#ffffff');
2301+
}
22412302
}
22422303

22432304
// Phaser looks for this by-default on initialization
@@ -2293,8 +2354,10 @@ class PacManScene extends Phaser.Scene {
22932354
this.load.image('s-key-logo', 'assets/keyboard-s-key-logo.png')
22942355
this.load.image('a-key-logo', 'assets/keyboard-a-key-logo.png')
22952356
this.load.image('d-key-logo', 'assets/keyboard-d-key-logo.png')
2357+
this.load.image('m-key-logo', 'assets/keyboard-m-key-logo.png')
22962358
this.load.image('esc-key-logo', 'assets/keyboard-esc-key-logo.png')
2297-
this.load.image('enter-key-logo', 'assets/keyboard-enter-key-logo.png')
2359+
this.load.image('enter-key-logo', 'assets/keyboard-enter-key-logo.png');
2360+
this.load.audio('bgm', ['assets/pvz-graze-the-roof-128k.mp3']);
22982361
}
22992362

23002363
create() {
@@ -2306,6 +2369,7 @@ class PacManScene extends Phaser.Scene {
23062369
this.animationsStarted = false; // Flag to prevent multiple animation starts
23072370
this.fontLoaded = false;
23082371
this.overlayOpen = false; // Track overlay state
2372+
this.bgmCaptionDynamicReady = false; // Mute caption stays "mute / unmute" until BGM actually plays
23092373
// this.canInteract = true; // Track if orb can be interacted with (to deal with race condition)
23102374

23112375
// Create section data
@@ -2351,6 +2415,8 @@ class PacManScene extends Phaser.Scene {
23512415

23522416
this.resize(); // Initial resize, also stores other parameters
23532417
this.scale.on('resize', this.resize, this); // Listen for resize events
2418+
2419+
this.setupBackgroundMusicAndMute();
23542420
}
23552421

23562422
update() {
@@ -2386,6 +2452,17 @@ class PacManScene extends Phaser.Scene {
23862452
this.instructionArrows.forEach(instruction => {
23872453
this.tweens.killTweensOf(instruction.arrow);
23882454
});
2455+
}
2456+
2457+
if (this.muteKey) {
2458+
this.muteKey.off('down', this.toggleMusicMute, this);
2459+
this.muteKey = null;
2460+
}
2461+
2462+
if (this.bgmSound) {
2463+
this.bgmSound.stop();
2464+
this.bgmSound.destroy();
2465+
this.bgmSound = null;
23892466
}
23902467

23912468
// Clean up all section content

0 commit comments

Comments
 (0)