86 lines
3.0 KiB
JavaScript
86 lines
3.0 KiB
JavaScript
import Phaser from '../vendor/phaser.js';
|
|
import { config } from '../config/Config.js';
|
|
import { toColor } from '../utils/Color.js';
|
|
import { canvasTexture } from '../utils/Textures.js';
|
|
|
|
const STAR_KEY = '__combat_star';
|
|
|
|
/**
|
|
* A slow diagonal-drifting starfield for the FIXED combat arena.
|
|
*
|
|
* The main game's Starfield (js/visuals/Starfield.js) is camera-driven —
|
|
* here the camera never moves, so the stars drift on their own and wrap
|
|
* at the screen edges, with a gentle per-star twinkle. Count + colors
|
|
* reuse data/game.json → starfield so the range matches the game sky.
|
|
*/
|
|
export class StarDrift {
|
|
/** @param {object} scene the combat scene */
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
const cfg = config.get('game.starfield', {});
|
|
this.enabled = cfg.enabled !== false;
|
|
this.count = Math.max(0, cfg.count ?? 140);
|
|
this.colors = (cfg.colors ?? ['#ffffff']).map((c) => toColor(c, 0xffffff));
|
|
this.speed = 4; // px/s diagonal drift (the arena's ambient current)
|
|
this.stars = [];
|
|
this.vx = 0;
|
|
this.vy = 0;
|
|
}
|
|
|
|
/** Lay the stars down across the screen. */
|
|
create(w, h) {
|
|
if (!this.enabled) return;
|
|
const scene = this.scene;
|
|
if (!scene.textures.exists(STAR_KEY)) {
|
|
canvasTexture(scene, STAR_KEY, 8, 8, (ctx, w, h) => {
|
|
const c = Math.min(w, h) / 2;
|
|
const g = ctx.createRadialGradient(c, c, 0, c, c, c);
|
|
g.addColorStop(0, 'rgba(255,255,255,1)');
|
|
g.addColorStop(0.6, 'rgba(255,255,255,0.7)');
|
|
g.addColorStop(1, 'rgba(255,255,255,0)');
|
|
ctx.fillStyle = g;
|
|
ctx.fillRect(0, 0, w, h);
|
|
});
|
|
}
|
|
|
|
const driftAngle = -0.6; // rad — a slow down-right current
|
|
this.vx = Math.cos(driftAngle) * this.speed;
|
|
this.vy = Math.sin(driftAngle) * this.speed;
|
|
|
|
for (let i = 0; i < this.count; i++) {
|
|
const star = scene
|
|
.add.image(Phaser.Math.FloatBetween(0, w), Phaser.Math.FloatBetween(0, h), STAR_KEY)
|
|
.setScale(Phaser.Math.FloatBetween(0.25, 1.1))
|
|
.setAlpha(Phaser.Math.FloatBetween(0.2, 0.8))
|
|
.setTint(this.colors[i % this.colors.length] ?? 0xffffff)
|
|
.setDepth(0);
|
|
star.baseAlpha = star.alpha;
|
|
star.tw = Phaser.Math.FloatBetween(0.5, 2.2); // twinkle rate (rad/s)
|
|
star.ph = Math.random() * Math.PI * 2;
|
|
this.stars.push(star);
|
|
}
|
|
}
|
|
|
|
/** Drift + wrap + twinkle. @param {number} time game ms @param {number} deltaMs */
|
|
update(time, deltaMs) {
|
|
if (!this.enabled || this.stars.length === 0) return;
|
|
const dt = deltaMs / 1000;
|
|
const w = this.scene.scale.width;
|
|
const h = this.scene.scale.height;
|
|
for (const star of this.stars) {
|
|
star.x += this.vx * dt;
|
|
star.y += this.vy * dt;
|
|
if (star.x < 0) star.x += w;
|
|
else if (star.x > w) star.x -= w;
|
|
if (star.y < 0) star.y += h;
|
|
else if (star.y > h) star.y -= h;
|
|
star.alpha = star.baseAlpha * (0.72 + 0.28 * Math.sin(time * 0.001 * star.tw + star.ph));
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
for (const star of this.stars) star.destroy();
|
|
this.stars.length = 0;
|
|
}
|
|
}
|