Compare commits
No commits in common. "d41183c1fa1298fe2d977cced3b3c039a4a30f3c" and "6ba71620b453c5aaf4da79ca4a6f1d55aab53a8d" have entirely different histories.
d41183c1fa
...
6ba71620b4
|
|
@ -32,5 +32,11 @@
|
||||||
"duration": [110, 340],
|
"duration": [110, 340],
|
||||||
"slices": [2, 6],
|
"slices": [2, 6],
|
||||||
"maxOffset": 12
|
"maxOffset": 12
|
||||||
|
},
|
||||||
|
"gameScene": {
|
||||||
|
"overlay": true,
|
||||||
|
"scanlineAlpha": 0.1,
|
||||||
|
"vignetteAlpha": 0.45,
|
||||||
|
"burstOnEntry": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { formatSystemReport } from '../galaxy/SystemReport.js';
|
||||||
import { Ship } from '../entities/Ship.js';
|
import { Ship } from '../entities/Ship.js';
|
||||||
import { Planet } from '../entities/Planet.js';
|
import { Planet } from '../entities/Planet.js';
|
||||||
import { Starfield } from '../visuals/Starfield.js';
|
import { Starfield } from '../visuals/Starfield.js';
|
||||||
|
import { CyberOverlay } from '../visuals/CyberOverlay.js';
|
||||||
|
|
||||||
const FONT_FALLBACK = "'Segoe UI', 'Helvetica Neue', Arial, sans-serif";
|
const FONT_FALLBACK = "'Segoe UI', 'Helvetica Neue', Arial, sans-serif";
|
||||||
const HEADER_FONT = () => fontStack('header', FONT_FALLBACK);
|
const HEADER_FONT = () => fontStack('header', FONT_FALLBACK);
|
||||||
|
|
@ -42,6 +43,14 @@ export class GameScene extends Phaser.Scene {
|
||||||
this.cameraFollowShip = config.get('game.camera.followShip', true);
|
this.cameraFollowShip = config.get('game.camera.followShip', true);
|
||||||
this.cameraFollowRate = config.get('game.camera.followRate', 3.0); // 1/s
|
this.cameraFollowRate = config.get('game.camera.followRate', 3.0); // 1/s
|
||||||
|
|
||||||
|
// The shared cyberpunk dressing (scanlines, vignette, occasional
|
||||||
|
// glitch burst) — the same overlay the menu uses, dialed down.
|
||||||
|
this.overlay = this.createThemeOverlay();
|
||||||
|
if (this.overlay && config.get('theme.gameScene.burstOnEntry', true)) {
|
||||||
|
// One arrival glitch when we cut in from the menu.
|
||||||
|
this.time.delayedCall(350, () => this.overlay?.trigger(320, 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
// We are, after all, in a system. Show the player which one. (This
|
// We are, after all, in a system. Show the player which one. (This
|
||||||
// also establishes the galaxy — and its seed — for what follows.)
|
// also establishes the galaxy — and its seed — for what follows.)
|
||||||
this.createSystemHud();
|
this.createSystemHud();
|
||||||
|
|
@ -153,12 +162,39 @@ export class GameScene extends Phaser.Scene {
|
||||||
line(`seed ${this.galaxy.seed}`, { fontFamily: fam, fontSize: '11px', color: '#3d476b' });
|
line(`seed ${this.galaxy.seed}`, { fontFamily: fam, fontSize: '11px', color: '#3d476b' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shared CRT/glitch overlay for this scene (data/theme.json →
|
||||||
|
* gameScene + overlay/glitch). Dialed down vs. the menu: fainter
|
||||||
|
* scanlines, lighter vignette — dressing, not the star of the show.
|
||||||
|
*/
|
||||||
|
createThemeOverlay() {
|
||||||
|
const theme = config.section('theme', {});
|
||||||
|
const gs = config.section('theme.gameScene', {});
|
||||||
|
if (gs.overlay === false) return null;
|
||||||
|
const overlay = theme.overlay ?? {};
|
||||||
|
return new CyberOverlay(this, {
|
||||||
|
scanline: {
|
||||||
|
pitch: overlay.scanline?.pitch ?? 3,
|
||||||
|
alpha: gs.scanlineAlpha ?? overlay.scanline?.alpha ?? 0.1,
|
||||||
|
},
|
||||||
|
grid: overlay.grid
|
||||||
|
? { cell: overlay.grid.cell ?? 48, alpha: (overlay.grid.alpha ?? 0.05) * 0.6 }
|
||||||
|
: undefined,
|
||||||
|
vignette: overlay.vignette
|
||||||
|
? { alpha: gs.vignetteAlpha ?? overlay.vignette.alpha ?? 0.4 }
|
||||||
|
: undefined,
|
||||||
|
sweep: overlay.sweep,
|
||||||
|
glitch: theme.glitch,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
update(_time, delta) {
|
update(_time, delta) {
|
||||||
// Phaser v4 (Giedi): the engine does not step the scene's TimeClock or
|
// Phaser v4 (Giedi): the engine does not step the scene's TimeClock or
|
||||||
// TweenManager — drive them here or delayedCall/addEvent/tweens never
|
// TweenManager — drive them here or delayedCall/addEvent/tweens never
|
||||||
// fire. (Same quirk as MenuScene.update; verified Sept 2026.)
|
// fire. (Same quirk as MenuScene.update; verified Sept 2026.)
|
||||||
this.time.update(_time, delta);
|
this.time.update(_time, delta);
|
||||||
this.tweens.update();
|
this.tweens.update();
|
||||||
|
this.overlay?.update(_time, delta);
|
||||||
this.ship.update(_time, delta);
|
this.ship.update(_time, delta);
|
||||||
// The home world is solid: the ship may come within the clearance in
|
// The home world is solid: the ship may come within the clearance in
|
||||||
// data/planets.json of its rim, but never closer (or through it).
|
// data/planets.json of its rim, but never closer (or through it).
|
||||||
|
|
@ -217,5 +253,6 @@ export class GameScene extends Phaser.Scene {
|
||||||
|
|
||||||
shutdown() {
|
shutdown() {
|
||||||
this.starfield?.destroy();
|
this.starfield?.destroy();
|
||||||
|
this.overlay?.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ export class CyberOverlay {
|
||||||
const band = Math.max(20, Math.round(this.cfg.sweep.band));
|
const band = Math.max(20, Math.round(this.cfg.sweep.band));
|
||||||
this.sweepBand = band;
|
this.sweepBand = band;
|
||||||
this.sweep = scene
|
this.sweep = scene
|
||||||
.add.image(w / 2, 0, T.sweep)
|
.add.image(0, 0, T.sweep)
|
||||||
.setOrigin(0.5)
|
.setOrigin(0.5)
|
||||||
.setScrollFactor(0)
|
.setScrollFactor(0)
|
||||||
.setDepth(d + 2)
|
.setDepth(d + 2)
|
||||||
|
|
@ -223,14 +223,14 @@ export class CyberOverlay {
|
||||||
const color = palette[(Math.random() * palette.length) | 0];
|
const color = palette[(Math.random() * palette.length) | 0];
|
||||||
const alpha = 0.06 + Math.random() * 0.18;
|
const alpha = 0.06 + Math.random() * 0.18;
|
||||||
bars.fillStyle(color, alpha);
|
bars.fillStyle(color, alpha);
|
||||||
bars.fillRect(dx - 24, y, w + 48, barH);
|
bars.fillRect(-w / 2 + dx - 24, y, w + 48, barH);
|
||||||
}
|
}
|
||||||
// One wider "displacement band" so the burst reads at a glance.
|
// One wider "displacement band" so the burst reads at a glance.
|
||||||
const bandY = Math.random() * h;
|
const bandY = Math.random() * h;
|
||||||
bars.fillStyle(0x04060d, 0.55);
|
bars.fillStyle(0x04060d, 0.55);
|
||||||
bars.fillRect(-24, bandY, w + 48, 14 + Math.random() * 22);
|
bars.fillRect(-w / 2 - 24, bandY, w + 48, 14 + Math.random() * 22);
|
||||||
bars.fillStyle(0x00e5ff, 0.22);
|
bars.fillStyle(0x00e5ff, 0.22);
|
||||||
bars.fillRect(-24, bandY - 2, w + 48, 2);
|
bars.fillRect(-w / 2 - 24, bandY - 2, w + 48, 2);
|
||||||
|
|
||||||
const die = (this.lastTime ?? this.scene.time.now) + this.burstDur + 60;
|
const die = (this.lastTime ?? this.scene.time.now) + this.burstDur + 60;
|
||||||
this.slices.push({ g: bars, die });
|
this.slices.push({ g: bars, die });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue