feat: enhance Jewel Quest and Shift game UI/UX

- Add custom background image for Jewel Quest menu screens
- Remove redundant title/subtitle text from Jewel Quest class and level select screens
- Reorganize Jewel Quest UI layout with improved positioning and semi-transparent text backgrounds
- Update Jewel Quest level select grid and status text positioning for better visual hierarchy
- Add background backdrop to Shift game "Choose Your Image" title for improved readability
This commit is contained in:
Brian Fertig 2026-07-26 18:00:47 -06:00
parent 9f54556ba9
commit f1c4289f0f
10 changed files with 36 additions and 26 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

@ -85,7 +85,10 @@ export const MANIFEST = {
...Array.from({ length: 6 }, (_, i) => ...Array.from({ length: 6 }, (_, i) =>
image(`bloxorz-bg-${i + 1}`, `assets/images/bloxorz/background-${i + 1}.png`)), image(`bloxorz-bg-${i + 1}`, `assets/images/bloxorz/background-${i + 1}.png`)),
], ],
jewelquest: [image('bg-jewelquest-battle', 'assets/images/background-jewelquest.png')], jewelquest: [
image('bg-jewelquest-battle', 'assets/images/background-jewelquest.png'),
image('bg-jewelquest-menu', 'assets/images/background-jewelquest-menu.png'),
],
bejeweled: [image('bg-bejeweled', 'assets/images/background-bejeweledblitz.png')], bejeweled: [image('bg-bejeweled', 'assets/images/background-bejeweledblitz.png')],
dominion: [ dominion: [
// Dominion card art. One 270×390 cell per card (art fills the top ~60%; // Dominion card art. One 270×390 cell per card (art fills the top ~60%;

View File

@ -88,8 +88,12 @@ export default class JewelQuestGame extends Phaser.Scene {
} catch (_) { /* private mode */ } } catch (_) { /* private mode */ }
this.makeTextures(); this.makeTextures();
// Solid felt background for non-battle screens (class select, level select, intro) // Background for non-battle screens (class select, level select, intro)
if (this.textures.exists('bg-jewelquest-menu')) {
this.add.image(GAME_WIDTH / 2, GAME_HEIGHT / 2, 'bg-jewelquest-menu').setDisplaySize(GAME_WIDTH, GAME_HEIGHT).setDepth(D.felt);
} else {
this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.felt); this.add.rectangle(GAME_WIDTH / 2, GAME_HEIGHT / 2, GAME_WIDTH, GAME_HEIGHT, FELT).setDepth(D.felt);
}
this.layer = this.add.container(0, 0); this.layer = this.add.container(0, 0);
if (this.playerClass) this.showLevelSelect(); if (this.playerClass) this.showLevelSelect();
@ -361,14 +365,6 @@ export default class JewelQuestGame extends Phaser.Scene {
this.clearLayer(); this.clearLayer();
const cx = GAME_WIDTH / 2; const cx = GAME_WIDTH / 2;
const title = this.add.text(cx, 80, 'JEWEL QUEST', {
fontFamily: 'Righteous', fontSize: '64px', color: COLORS.goldHex,
}).setOrigin(0.5);
const sub = this.add.text(cx, 138, 'Choose your champion. Match gems for mana, match skulls for damage, and spend mana on spells.', {
fontFamily: '"Julius Sans One"', fontSize: '22px', color: COLORS.mutedHex,
}).setOrigin(0.5);
this.layer.add([title, sub]);
const loadout = this.loadout(); const loadout = this.loadout();
const ids = Object.keys(CLASSES); const ids = Object.keys(CLASSES);
const CARD_W = 430; const CARD_W = 430;
@ -376,7 +372,7 @@ export default class JewelQuestGame extends Phaser.Scene {
const GAP = 26; const GAP = 26;
const totalW = ids.length * CARD_W + (ids.length - 1) * GAP; const totalW = ids.length * CARD_W + (ids.length - 1) * GAP;
const left = cx - totalW / 2 + CARD_W / 2; const left = cx - totalW / 2 + CARD_W / 2;
const cy = 540; const cy = 640;
ids.forEach((id, i) => { ids.forEach((id, i) => {
const cls = CLASSES[id]; const cls = CLASSES[id];
@ -459,14 +455,6 @@ export default class JewelQuestGame extends Phaser.Scene {
this.clearLayer(); this.clearLayer();
const cx = GAME_WIDTH / 2; const cx = GAME_WIDTH / 2;
const title = this.add.text(cx, 78, 'JEWEL QUEST', {
fontFamily: 'Righteous', fontSize: '60px', color: COLORS.goldHex,
}).setOrigin(0.5);
const sub = this.add.text(cx, 130, 'Match 3+ gems to bank mana, match skulls to deal damage, and cast spells to break your rival.', {
fontFamily: '"Julius Sans One"', fontSize: '22px', color: COLORS.mutedHex,
}).setOrigin(0.5);
this.layer.add([title, sub]);
if (!this.bank.length) { if (!this.bank.length) {
const msg = this.add.text(cx, 520, 'No levels found in /data/jewelquest.json', { const msg = this.add.text(cx, 520, 'No levels found in /data/jewelquest.json', {
fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.dangerHex, align: 'center', fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.dangerHex, align: 'center',
@ -486,20 +474,27 @@ export default class JewelQuestGame extends Phaser.Scene {
`Spells ${loadout.spellCount}/5`, `Spells ${loadout.spellCount}/5`,
nextMs ? `Next bonus after Level ${nextMs.afterLevel}` : 'All bonuses earned', nextMs ? `Next bonus after Level ${nextMs.afterLevel}` : 'All bonuses earned',
].join(' • '); ].join(' • ');
const prog = this.add.text(cx, 176, `Defeated ${this.levelsCompleted} / ${this.bank.length}`, { const prog = this.add.text(cx, 376, `Defeated ${this.levelsCompleted} / ${this.bank.length}`, {
fontFamily: 'Righteous', fontSize: '24px', color: COLORS.textHex, fontFamily: 'Righteous', fontSize: '24px', color: COLORS.textHex,
}).setOrigin(0.5); }).setOrigin(0.5);
const loadoutText = this.add.text(cx, 216, strip, { const loadoutText = this.add.text(cx, 416, strip, {
fontFamily: '"Julius Sans One"', fontSize: '20px', color: COLORS.goldHex, fontFamily: '"Julius Sans One"', fontSize: '20px', color: COLORS.goldHex,
}).setOrigin(0.5); }).setOrigin(0.5);
this.layer.add([prog, loadoutText]);
// Semi-transparent background behind the status text
const bgW = Math.max(prog.width, loadoutText.width) + 60;
const bgH = 120;
const bg = this.add.graphics().setDepth(D.ui - 1);
bg.fillStyle(0x000000, 0.65);
bg.fillRoundedRect(cx - bgW / 2, 316, bgW, bgH, 12);
this.layer.add([bg, prog, loadoutText]);
const COLS = 10; const COLS = 10;
const TILE = 128; const TILE = 128;
const GAP = 16; const GAP = 16;
const gridW = COLS * TILE + (COLS - 1) * GAP; const gridW = COLS * TILE + (COLS - 1) * GAP;
const left = cx - gridW / 2 + TILE / 2; const left = cx - gridW / 2 + TILE / 2;
const top = 330; const top = 530;
this.bank.forEach((lv, i) => { this.bank.forEach((lv, i) => {
const col = i % COLS; const col = i % COLS;
@ -619,7 +614,14 @@ export default class JewelQuestGame extends Phaser.Scene {
const statText = this.add.text(cx, 800, `Skill ${stars} HP ❤ ${lv.hp} Class ${enemyCls}`, { const statText = this.add.text(cx, 800, `Skill ${stars} HP ❤ ${lv.hp} Class ${enemyCls}`, {
fontFamily: '"Julius Sans One"', fontSize: '28px', color: COLORS.textHex, fontFamily: '"Julius Sans One"', fontSize: '28px', color: COLORS.textHex,
}).setOrigin(0.5); }).setOrigin(0.5);
this.layer.add([name, bio, tagline, statText]);
// Semi-transparent background behind the opponent info text
const bgW = Math.max(name.width, bio.width, tagline.width, statText.width) + 60;
const bgH = 240;
const bg = this.add.graphics().setDepth(D.ui - 1);
bg.fillStyle(0x000000, 0.65);
bg.fillRoundedRect(cx - bgW / 2, 600, bgW, bgH, 12);
this.layer.add([bg, name, bio, tagline, statText]);
const fight = new Button(this, cx - 130, GAME_HEIGHT - 110, 'FIGHT!', () => this.startBattle(level), const fight = new Button(this, cx - 130, GAME_HEIGHT - 110, 'FIGHT!', () => this.startBattle(level),
{ width: 240, height: 66, fontSize: 30 }); { width: 240, height: 66, fontSize: 30 });

View File

@ -223,10 +223,15 @@ export default class ShiftGame extends Phaser.Scene {
this._drawMenuBackground(); this._drawMenuBackground();
const cx = GAME_WIDTH / 2; const cx = GAME_WIDTH / 2;
const titleBg = this.add.graphics().setDepth(D.overlay - 1);
titleBg.fillStyle(0x000000, 0.55);
titleBg.fillRoundedRect(cx - 310, 75, 620, 90, 12);
titleBg.lineStyle(2, 0xffffff, 0.3);
titleBg.strokeRoundedRect(cx - 310, 75, 620, 90, 12);
const title = this.add.text(cx, 120, 'Choose Your Image', { const title = this.add.text(cx, 120, 'Choose Your Image', {
fontFamily: 'Righteous', fontSize: '64px', color: COLORS.goldHex, fontFamily: 'Righteous', fontSize: '64px', color: COLORS.goldHex,
}).setOrigin(0.5); }).setOrigin(0.5);
this.layer.add(title); this.layer.add([titleBg, title]);
const CARD_W = 310; const CARD_W = 310;
const CARD_H = 360; const CARD_H = 360;