feat: Add main menu assets and refactor puzzle thumbnail handling
- Add main menu UI image and background music (with updated track metadata) - Rename puzzle assets to include `.png` extensions for consistency - Introduce `thumbnails.json` manifest to decouple thumbnail paths from puzzle data - Update `NewPuzzleScene.js` to load thumbnails explicitly via manifest instead of inferring paths - Update `PuzzleScene.js` to ensure full puzzle images are loaded fresh on initial entry (not during network joins or restores)
|
|
@ -1,22 +1,22 @@
|
|||
[
|
||||
{
|
||||
"path": "assets/audio/music/track_01.mp3",
|
||||
"title": "Track 01",
|
||||
"artist": "Unknown Artist"
|
||||
"title": "Digital Memories",
|
||||
"artist": "AI Com Truise"
|
||||
},
|
||||
{
|
||||
"path": "assets/audio/music/track_02.mp3",
|
||||
"title": "Track 02",
|
||||
"artist": "Unknown Artist"
|
||||
"title": "Synthwave Highway",
|
||||
"artist": "AI The Midnight"
|
||||
},
|
||||
{
|
||||
"path": "assets/audio/music/track_03.mp3",
|
||||
"title": "Track 03",
|
||||
"artist": "Unknown Artist"
|
||||
"title": "Orbital Perspective",
|
||||
"artist": "AI Tangerine Dream"
|
||||
},
|
||||
{
|
||||
"path": "assets/audio/music/track_04.mp3",
|
||||
"title": "Track 04",
|
||||
"artist": "Unknown Artist"
|
||||
"title": "Just Puzzlin'",
|
||||
"artist": "AI Earthless"
|
||||
}
|
||||
]
|
||||
|
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 3.8 MiB |
|
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 3.8 MiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 386 KiB |
|
Before Width: | Height: | Size: 4.2 MiB After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
|
@ -41,7 +41,7 @@
|
|||
},
|
||||
{
|
||||
"key": "puzzle_misty",
|
||||
"path": "assets/images/puzzles/misty_exploration",
|
||||
"path": "assets/images/puzzles/misty_exploration.png",
|
||||
"label": "Misty Exploration"
|
||||
},
|
||||
{
|
||||
|
|
@ -66,12 +66,12 @@
|
|||
},
|
||||
{
|
||||
"key": "puzzle_mandrill",
|
||||
"path": "assets/images/puzzles/thoughtful_mandrill",
|
||||
"path": "assets/images/puzzles/thoughtful_mandrill.png",
|
||||
"label": "Thoughtful Mandrill"
|
||||
},
|
||||
{
|
||||
"key": "puzzle_ultimate_tree_fort",
|
||||
"path": "assets/images/puzzles/ultimate_tree_fort",
|
||||
"path": "assets/images/puzzles/ultimate_tree_fort.png",
|
||||
"label": "Ultimate Tree Fort"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
[
|
||||
{
|
||||
"key": "thumb_america",
|
||||
"path": "assets/images/puzzles/thumb_america.png",
|
||||
"puzzleKey": "puzzle_america"
|
||||
},
|
||||
{
|
||||
"key": "thumb_dwarven_mining_village",
|
||||
"path": "assets/images/puzzles/thumb_dwarven_mining_village.png",
|
||||
"puzzleKey": "puzzle_dwarven_mining_village"
|
||||
},
|
||||
{
|
||||
"key": "thumb_golden_in_the_mountains",
|
||||
"path": "assets/images/puzzles/thumb_golden_in_the_mountains.png",
|
||||
"puzzleKey": "puzzle_golden_in_the_mountains"
|
||||
},
|
||||
{
|
||||
"key": "thumb_good_vs_evil",
|
||||
"path": "assets/images/puzzles/thumb_good_vs_evil.png",
|
||||
"puzzleKey": "puzzle_good_vs_evil"
|
||||
},
|
||||
{
|
||||
"key": "thumb_growing_ea",
|
||||
"path": "assets/images/puzzles/thumb_growing_ea.png",
|
||||
"puzzleKey": "puzzle_growing_ea"
|
||||
},
|
||||
{
|
||||
"key": "thumb_guilin_landscape",
|
||||
"path": "assets/images/puzzles/thumb_guilin_landscape.png",
|
||||
"puzzleKey": "puzzle_guilin_landscape"
|
||||
},
|
||||
{
|
||||
"key": "thumb_home_sweet_home",
|
||||
"path": "assets/images/puzzles/thumb_home_sweet_home.png",
|
||||
"puzzleKey": "puzzle_home_sweet_home"
|
||||
},
|
||||
{
|
||||
"key": "thumb_lone_ship",
|
||||
"path": "assets/images/puzzles/thumb_lone_ship_in_the_seas.png",
|
||||
"puzzleKey": "puzzle_lone_ship"
|
||||
},
|
||||
{
|
||||
"key": "thumb_misty",
|
||||
"path": "assets/images/puzzles/thumb_misty_exploration.png",
|
||||
"puzzleKey": "puzzle_misty"
|
||||
},
|
||||
{
|
||||
"key": "thumb_model_village",
|
||||
"path": "assets/images/puzzles/thumb_model_village.png",
|
||||
"puzzleKey": "puzzle_model_village"
|
||||
},
|
||||
{
|
||||
"key": "thumb_opulant_flowers",
|
||||
"path": "assets/images/puzzles/thumb_opulant_flowers.png",
|
||||
"puzzleKey": "puzzle_opulant_flowers"
|
||||
},
|
||||
{
|
||||
"key": "thumb_robot_in_a_flavela",
|
||||
"path": "assets/images/puzzles/thumb_robot_in_a_flavela.png",
|
||||
"puzzleKey": "puzzle_robot_in_a_flavela"
|
||||
},
|
||||
{
|
||||
"key": "thumb_disassembled_android",
|
||||
"path": "assets/images/puzzles/thumb_the_disassembled_android.png",
|
||||
"puzzleKey": "puzzle_disassembled_android"
|
||||
},
|
||||
{
|
||||
"key": "thumb_mandrill",
|
||||
"path": "assets/images/puzzles/thumb_thoughtful_mandrill.png",
|
||||
"puzzleKey": "puzzle_mandrill"
|
||||
},
|
||||
{
|
||||
"key": "thumb_ultimate_tree_fort",
|
||||
"path": "assets/images/puzzles/thumb_ultimate_tree_fort.png",
|
||||
"puzzleKey": "puzzle_ultimate_tree_fort"
|
||||
}
|
||||
]
|
||||
|
|
@ -18,8 +18,9 @@ class NewPuzzleScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
preload() {
|
||||
// Load the puzzle list JSON; images are loaded dynamically in create()
|
||||
// Load puzzle list and thumbnail manifest; full images are loaded by PuzzleScene
|
||||
this.load.json('puzzle_list', 'assets/puzzles.json');
|
||||
this.load.json('thumbnail_list', 'assets/thumbnails.json');
|
||||
}
|
||||
|
||||
create() {
|
||||
|
|
@ -59,12 +60,18 @@ class NewPuzzleScene extends Phaser.Scene {
|
|||
sep.fillTriangle(960, 100, 966, 105, 960, 110);
|
||||
sep.fillTriangle(960, 100, 954, 105, 960, 110);
|
||||
|
||||
// Read puzzle list from cache, then load any images not yet in the texture cache
|
||||
// Read puzzle list and thumbnail manifest from cache
|
||||
this._puzzleImages = this.cache.json.get('puzzle_list');
|
||||
this._thumbnails = this.cache.json.get('thumbnail_list') || [];
|
||||
|
||||
const toLoad = this._puzzleImages.filter(img => !this.textures.exists(img.key));
|
||||
// Build a lookup from puzzleKey -> thumbnail entry
|
||||
this._thumbByPuzzleKey = {};
|
||||
this._thumbnails.forEach(t => { this._thumbByPuzzleKey[t.puzzleKey] = t; });
|
||||
|
||||
// Only load thumbnail textures (full images are loaded by PuzzleScene)
|
||||
const toLoad = this._thumbnails.filter(t => !this.textures.exists(t.key));
|
||||
if (toLoad.length > 0) {
|
||||
toLoad.forEach(img => this.load.image(img.key, img.path));
|
||||
toLoad.forEach(t => this.load.image(t.key, t.path));
|
||||
this.load.once('complete', () => this._buildDomUI());
|
||||
this.load.start();
|
||||
} else {
|
||||
|
|
@ -131,9 +138,8 @@ class NewPuzzleScene extends Phaser.Scene {
|
|||
});
|
||||
|
||||
const thumb = document.createElement('img');
|
||||
// Use thumbnail version: insert "thumb_" before the filename
|
||||
const lastSlash = img.path.lastIndexOf('/');
|
||||
thumb.src = img.path.substring(0, lastSlash + 1) + 'thumb_' + img.path.substring(lastSlash + 1);
|
||||
const thumbEntry = this._thumbByPuzzleKey[img.key];
|
||||
thumb.src = thumbEntry ? thumbEntry.path : img.path;
|
||||
Object.assign(thumb.style, {
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
|
|
|
|||
|
|
@ -106,6 +106,13 @@ class PuzzleScene extends Phaser.Scene {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fresh start from NewPuzzleScene — load the full image if not cached
|
||||
if (!this.cfg._networkJoin && !this.cfg._restore) {
|
||||
if (!this.textures.exists(this.cfg.imageKey)) {
|
||||
this.load.image(this.cfg.imageKey, this.cfg.imagePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create() {
|
||||
|
|
|
|||