diff --git a/assets/videos/rocky-shop-03.mp4 b/assets/videos/rocky-shop-03.mp4 new file mode 100644 index 0000000..b0dae54 Binary files /dev/null and b/assets/videos/rocky-shop-03.mp4 differ diff --git a/data/landing.json b/data/landing.json index 3027fc6..37d594d 100644 --- a/data/landing.json +++ b/data/landing.json @@ -50,7 +50,7 @@ { "land": "gasgiant-land-02.mp4", "surface": "gasgiant-surface-02.mp4", "takeoff": "gasgiant-takeoff-02.mp4", "shop": "gasgiant-shop-02.mp4" }, { "land": "gasgiant-land-03.mp4", "surface": "gasgiant-surface-03.mp4", "takeoff": "gasgiant-takeoff-03.mp4", "shop": "gasgiant-shop-03.mp4" }, { "land": "rocky-land-01.mp4", "surface": "rocky-surface-01.mp4", "takeoff": "rocky-takeoff-01.mp4", "shop": "terran-shop-01.mp4" }, - { "land": "gasgiant-land-02.mp4", "surface": "gasgiant-surface-02.mp4", "takeoff": "gasgiant-takeoff-02.mp4", "shop": "terran-shop-01.mp4" }, - { "land": "rocky-land-03.mp4", "surface": "terran-surface-01.mp4", "takeoff": "gasgiant-takeoff-03.mp4", "shop": "terran-shop-01.mp4" } + { "land": "rocky-land-02.mp4", "surface": "rocky-surface-02.mp4", "takeoff": "rocky-takeoff-02.mp4", "shop": "rocky-shop-02.mp4" }, + { "land": "rocky-land-03.mp4", "surface": "rocky-surface-03.mp4", "takeoff": "rocky-takeoff-03.mp4", "shop": "rocky-shop-03.mp4" } ] } diff --git a/js/scenes/GameScene.js b/js/scenes/GameScene.js index 4a35dbc..6db4c16 100644 --- a/js/scenes/GameScene.js +++ b/js/scenes/GameScene.js @@ -367,10 +367,12 @@ export class GameScene extends Phaser.Scene { typeof rec.frame === 'number' ? rec.frame : Planet.frameFor(kind, Rng.derive(this.galaxy.seed, 'planet', rec.name)); - const tint = config.get(`planets.classTint.${kind}`); + // (PLANET TINT — REMOVED FOR NOW: per-class canvas tints used to be + // applied here from data/planets.json → classTint, i.e. + // `tint: toColor(config.get(`planets.classTint.${kind}`))`. The + // Planet still accepts the option — pass it back when we want it.) const p = new Planet(this, rec.x, rec.y, frame, kind, { scale: rec.scale ?? 1, - tint: tint === undefined ? undefined : toColor(tint), }); p.setDepth(5); p.discoveryId = rec.name; // unique within the system @@ -2980,13 +2982,17 @@ export class GameScene extends Phaser.Scene { this.scene.start('MenuScene'); } - /** The sub-bar's anchor: the MENU button's center + top edge. */ + /** The sub-bar's anchor: the MENU button's center x + width, and the + * deck's TOP EDGE as the resting line — the sub-bar rests on the bottom + * bar (the deck), not on the button (the buttons are inset below the + * bar's top rail, so anchoring to the button made the sub-bar spill + * over the deck's top edge). */ menuAnchor() { const menuSlot = this.actionBar?.slots?.find((s) => s.id === 'menu'); if (menuSlot) { return { x: menuSlot.slot.x, - y: menuSlot.slot.y - this.actionBar.style.bh / 2, + y: this.actionBar.rect.y, // deck top edge — the sub-bar's bottom edge sits on it w: this.actionBar.style.bw, }; } diff --git a/js/scenes/SurfaceScene.js b/js/scenes/SurfaceScene.js index ed2cb06..b1a47c2 100644 --- a/js/scenes/SurfaceScene.js +++ b/js/scenes/SurfaceScene.js @@ -790,7 +790,9 @@ export class SurfaceScene extends Phaser.Scene { if (menuSlot) { return { x: menuSlot.slot.x, - y: menuSlot.slot.y - this.actionBar.style.bh / 2, + // Deck top edge — the sub-bar rests on the bottom bar (the deck), + // not on the button (buttons are inset below the top rail). + y: this.actionBar.rect.y, w: this.actionBar.style.bw, }; } diff --git a/js/ui/MenuSubBar.js b/js/ui/MenuSubBar.js index 3dcf915..12e2c33 100644 --- a/js/ui/MenuSubBar.js +++ b/js/ui/MenuSubBar.js @@ -16,7 +16,7 @@ import { ScrambleDecode, decodeDur } from '../utils/Decode.js'; * THE OPEN — a signal unfolding out of the seam (bottom-up, ~340 ms): * t=0 the deck fires a glitch burst (slice bars + its panel's RGB * pull-apart — the scene triggers it), the camera kicks, and a - * hot seam line flares along the button's top edge; + * hot seam line flares along the deck's top rail; * 0→H a bright UNFOLD EDGE climbs the panel — the body is redrawn * taller every frame behind it (the deck grows out of the * button), a cyan→magenta rail rides the edge, the scanlines @@ -48,7 +48,9 @@ export class MenuSubBar extends Phaser.GameObjects.Container { /** * @param {Phaser.Scene} scene * @param {object} [o] { - * anchor: { x, y, w } — the menu button's center (x, y) + width (screen px) + * anchor: { x, y, w } — the menu button's center x + width (screen px), + * y = the RESTING LINE (the command deck's top edge — + * the bar's bottom edge sits on it, above the button) * onAction?: (id) => void * } */ @@ -176,11 +178,12 @@ export class MenuSubBar extends Phaser.GameObjects.Container { // ghost buttons must be switched off via `input.enabled`, or they // swallow every world click in their band (and the bar starts closed). this.buttons.forEach((s) => setInteractiveEnabled(s.btn.panel, false)); - // ---- the anchor: right-aligned over the menu button, seam on its top edge + // ---- the anchor: right-aligned over the menu button, bottom edge on + // the resting line (the deck's top edge — the bar sits on the bar) const a = o.anchor ?? { x: sceneW / 2, y: scene.scale.height - 60, w: 120 }; let cx = a.x + a.w / 2 - this.W / 2; // bar's right edge on the button's right edge cx = Phaser.Math.Clamp(cx, this.W / 2 + 12, sceneW - this.W / 2 - 12); - const seamY = a.y - 0; // the bar's bottom edge sits ON the button (seam = button top) + const seamY = a.y - 0; // the bar's bottom edge sits ON the deck's top edge this.seamY = seamY; this.setPosition(cx, seamY); this.rect = { x: cx - this.W / 2, y: seamY - H, w: this.W, h: H }; @@ -386,7 +389,7 @@ export class MenuSubBar extends Phaser.GameObjects.Container { stroke(this.ghostM, this.magenta); } - /** The seam power line (on the button's top edge), width animated. */ + /** The seam power line (on the resting line — the deck's top rail), width animated. */ drawSeam(width, alpha) { const g = this.seamG; g.clear();