feat(jewelquest): enhance battle visuals and add sword SFX
- Add dedicated battle background image, separate from non-battle screens - Move felt background to render after textures are loaded - Fix callout text z-ordering so it always renders above jewels/FX - Play sword-hit SFX on skull matches, sword-slice on damage - Register new audio assets and sound constants
This commit is contained in:
parent
d01a2917b1
commit
c74fc88e04
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
|
|
@ -57,7 +57,7 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
if (music?.tracks) new MusicPlayer(this, music.tracks);
|
||||
} catch (_) { /* optional */ }
|
||||
|
||||
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.felt);
|
||||
|
||||
|
||||
const raw = this.cache.json.get('jewelquest');
|
||||
this.config = raw ?? this.config;
|
||||
|
|
@ -83,6 +83,9 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
} catch (_) { /* private mode */ }
|
||||
|
||||
this.makeTextures();
|
||||
// Solid felt background for non-battle screens (class select, level select, intro)
|
||||
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.felt);
|
||||
|
||||
this.layer = this.add.container(0, 0);
|
||||
if (this.playerClass) this.showLevelSelect();
|
||||
else this.showClassSelect();
|
||||
|
|
@ -197,6 +200,7 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
this.selected = null;
|
||||
this.dragFrom = null;
|
||||
this.layer.removeAll(true);
|
||||
if (this.calloutText) { this.calloutText.destroy(); this.calloutText = null; }
|
||||
this.cellSprites = null;
|
||||
this.spellButtons = null;
|
||||
}
|
||||
|
|
@ -540,6 +544,9 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
}
|
||||
|
||||
drawBattleChrome() {
|
||||
// Battle-only background
|
||||
this.add.image(GAME_WIDTH / 2, GAME_HEIGHT / 2, 'bg-jewelquest-battle').setDisplaySize(GAME_WIDTH, GAME_HEIGHT).setDepth(D.felt);
|
||||
|
||||
const cx = GAME_WIDTH / 2;
|
||||
const hud = this.add.text(cx, 52, `Level ${this.level} — vs ${this.opponent.name}`, {
|
||||
fontFamily: 'Righteous', fontSize: '36px', color: COLORS.goldHex,
|
||||
|
|
@ -593,11 +600,10 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
|
||||
this.drawSpellPanel();
|
||||
|
||||
// callout
|
||||
// callout — not in container so it always renders above jewels/fx
|
||||
this.calloutText = this.add.text(cx, 540, '', {
|
||||
fontFamily: 'Righteous', fontSize: '54px', color: COLORS.goldHex, stroke: '#000000', strokeThickness: 6,
|
||||
}).setOrigin(0.5).setDepth(D.fx).setAlpha(0);
|
||||
this.layer.add(this.calloutText);
|
||||
}).setOrigin(0.5).setDepth(D.ui + 5).setAlpha(0);
|
||||
|
||||
const quit = new Button(this, 140, GAME_HEIGHT - 50, 'Levels', () => this.showLevelSelect(),
|
||||
{ variant: 'ghost', width: 180, height: 52, fontSize: 22 });
|
||||
|
|
@ -894,7 +900,8 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
this.flashCells([e.a, e.b], 0xffffff);
|
||||
break;
|
||||
case 'clear': {
|
||||
playSound(this, SFX.MASTERMIND_MATCH ?? SFX.CARD_SHOW);
|
||||
const hasSkullMatch = (e.groups ?? []).some((grp) => grp.cls === 'skull' && grp.cells.length >= 3);
|
||||
playSound(this, hasSkullMatch ? SFX.SWORD_HIT : (SFX.MASTERMIND_MATCH ?? SFX.CARD_SHOW));
|
||||
const actorPanel = PANEL_X[e.actor];
|
||||
const foePanel = PANEL_X[1 - e.actor];
|
||||
for (const grp of e.groups ?? []) {
|
||||
|
|
@ -929,6 +936,7 @@ export default class JewelQuestGame extends Phaser.Scene {
|
|||
break;
|
||||
}
|
||||
case 'damage':
|
||||
playSound(this, SFX.SWORD_SLICE);
|
||||
this.floatText(PANEL_X[e.target], 320, `-${e.amount}`, GEM_HEX.red, PANEL_X[e.target], 376);
|
||||
this.updateMetersFrom(e);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ export default class PreloadScene extends Phaser.Scene {
|
|||
this.load.image('bg-menu', '/assets/images/background-menu.png');
|
||||
this.load.image('bg-room', '/assets/images/background-room.png');
|
||||
this.load.image('bg-casino', '/assets/images/background-casino.png');
|
||||
this.load.image('bg-jewelquest-battle', '/assets/images/background-jewelquest.png');
|
||||
this.load.image('main-title', '/assets/images/main-title.png');
|
||||
this.load.json('playfields', '/data/playfields.json');
|
||||
this.load.json('card-backs', '/data/card-backs.json');
|
||||
|
|
@ -100,6 +101,8 @@ export default class PreloadScene extends Phaser.Scene {
|
|||
this.load.audio('sfx-battleship-miss', '/assets/fx/battleship-miss.mp3');
|
||||
this.load.audio('sfx-battleship-launch', '/assets/fx/battleship-launch.mp3');
|
||||
this.load.audio('sfx-victory-short', '/assets/fx/victory-short.mp3');
|
||||
this.load.audio('sfx-sword-hit', '/assets/fx/sword-hit.mp3');
|
||||
this.load.audio('sfx-sword-slice', '/assets/fx/sword-slice.mp3');
|
||||
this.load.audio('sfx-scifi-launch', '/assets/fx/scifi-launch.mp3');
|
||||
this.load.audio('sfx-scifi-explode', '/assets/fx/scifi-explode.mp3');
|
||||
this.load.audio('sfx-scifi-riser', '/assets/fx/scifi-riser.mp3');
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ export const SFX = {
|
|||
SCIFI_RISER: 'sfx-scifi-riser',
|
||||
SCIFI_REVEAL: 'sfx-scifi-reveal',
|
||||
SCIFI_WOOSH: 'sfx-scifi-woosh',
|
||||
SWORD_HIT: 'sfx-sword-hit',
|
||||
SWORD_SLICE: 'sfx-sword-slice',
|
||||
MONOPOLY_PURCHASE: 'sfx-monopoly-purchase',
|
||||
MONOPOLY_EXPENSE: 'sfx-monopoly-expense',
|
||||
MONOPAY: 'sfx-monopoly-pay',
|
||||
|
|
|
|||
Loading…
Reference in New Issue