feat: add Chinese soundtrack to Mahjong and Mahjong Match games

- Register 'chinese' music override for mahjong and mahjongmatch in soundtrack config
- Preload chinese-music.json in PreloadScene
- Lazy-load Chinese music assets via asset manifest for both games
- Update game scenes to use getGameSoundtrack() with volume support
- Update mahjong match background images (01, 02)
This commit is contained in:
Brian Fertig 2026-07-26 10:45:43 -06:00
parent 386ad3efb7
commit cfbf1032bf
7 changed files with 21 additions and 5 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -131,13 +131,21 @@ export const MANIFEST = {
sheet('jello-items', 'assets/images/jello-items.png', 132, 132),
image('bg-puddingmonsters-menu', 'assets/images/background-jello.png'),
],
mahjong: MAHJONG_TILES,
mahjong: [
...MAHJONG_TILES,
// chinese soundtrack (see services/soundtrack.js) — lazy-loaded here so
// its audio only downloads once Mahjong is actually entered.
(scene) => musicFrom(scene, 'chinese-music'),
],
mahjongmatch: [
...MAHJONG_TILES,
// Carries its own title, so the layout-select screen draws no heading.
image('bg-mahjongmatch-menu', 'assets/images/background-mahjongmatch.png'),
// In-play backdrops — one is picked at random per game.
...['01', '02', '03'].map((n) => image(`bg-mm-${n}`, `assets/images/background-mm-${n}.png`)),
// chinese soundtrack (see services/soundtrack.js) — lazy-loaded here so
// its audio only downloads once Mahjong Match is actually entered.
(scene) => musicFrom(scene, 'chinese-music'),
],
spireclimb: [
image('spireclimb-act1', 'assets/images/spireclimb-act1.png'),

View File

@ -6,6 +6,7 @@ import { api } from '../../services/api.js';
import { createOpponentPortrait, createPlayerPortrait } from '../../ui/Portrait.js';
import { playSound, SFX } from '../../ui/Sounds.js';
import { MusicPlayer } from '../../ui/MusicPlayer.js';
import { getGameSoundtrack } from '../../services/soundtrack.js';
import {
TILES, SUIT_NAMES, WIND_NAMES, rankOf, isSuited,
FAAN_TABLE, MIN_FAAN, PLAYER_COLOR_HEX,
@ -76,7 +77,10 @@ export default class MahjongGame extends Phaser.Scene {
}
create() {
try { new MusicPlayer(this, this.cache.json.get('music')?.tracks ?? []); } catch { /* optional */ }
try {
const { tracks, volume } = getGameSoundtrack(this);
if (tracks.length) new MusicPlayer(this, tracks, volume);
} catch { /* optional */ }
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(DEPTH.bg);
const names = [auth.user?.username ?? 'You'];

View File

@ -2,6 +2,7 @@ import * as Phaser from 'phaser';
import { GAME_WIDTH, GAME_HEIGHT, COLORS } from '../../config.js';
import { Button } from '../../ui/Button.js';
import { MusicPlayer } from '../../ui/MusicPlayer.js';
import { getGameSoundtrack } from '../../services/soundtrack.js';
import { playSound, playSoundEx, SFX } from '../../ui/Sounds.js';
import { api } from '../../services/api.js';
import {
@ -81,8 +82,8 @@ export default class MahjongMatchGame extends Phaser.Scene {
create() {
try {
const music = this.cache.json.get('music');
if (music?.tracks) new MusicPlayer(this, music.tracks);
const { tracks, volume } = getGameSoundtrack(this);
if (tracks.length) new MusicPlayer(this, tracks, volume);
} catch (_) { /* optional */ }
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.bg);

View File

@ -47,6 +47,7 @@ export default class PreloadScene extends Phaser.Scene {
this.load.json('arcadedark-music', 'data/arcadedark-music.json');
this.load.json('hacker-music', 'data/hacker-music.json');
this.load.json('adventure-music', 'data/adventure-music.json');
this.load.json('chinese-music', 'data/chinese-music.json');
this.load.json('advancewars-artwork', 'data/advancewars-artwork.json');
this.load.json('tetrisattack-artwork', 'data/tetrisattack-artwork.json');
this.load.json('totalannihilation-artwork', 'data/totalannihilation-artwork.json');

View File

@ -29,7 +29,9 @@ export const GAME_SOUNDTRACK_OVERRIDES = {
dotlink: 'hacker',
'2048': 'hacker',
swdbg: 'adventure',
spireclimb: 'adventure'
spireclimb: 'adventure',
mahjong: 'chinese',
mahjongmatch: 'chinese',
};
// Resolve the track list (and optional volume override) a game scene's