Fix menu sub-bar anchor to rest on deck top edge, not button

- The sub-bar was anchored to the MENU button's center + half-height, which
  made it spill over the command deck's top rail (buttons are inset below
  the bar's top edge). Anchor y is now the deck's top edge so the bar's
  bottom edge sits on the deck.
- Update landing.json rocky land-02/03 entries to reference their own
  rocky surface/takeoff/shop videos instead of reusing gasgiant/terran
  assets, and add the new rocky-shop-03.mp4 video.
- Temporarily disable per-class planet tints in GameScene (option still
  accepted by Planet for when we re-enable it).
This commit is contained in:
Brian Fertig 2026-09-07 12:23:50 -06:00
parent 546e5c9bf3
commit 8f6e7bf539
5 changed files with 23 additions and 12 deletions

Binary file not shown.

View File

@ -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" }
]
}

View File

@ -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,
};
}

View File

@ -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,
};
}

View File

@ -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;
* 0H a bright UNFOLD EDGE climbs the panel the body is redrawn
* taller every frame behind it (the deck grows out of the
* button), a cyanmagenta 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();