Skip to content

Commit 1f5e000

Browse files
committed
tweak(client): hero selection halo uses a soft radial-gradient texture
Replace the flat white Arc with a lazily-built CanvasTexture whose radial gradient fades 0.9 → 0 alpha from center to edge. The halo now reads as a soft light instead of a visible circle. Texture key 'hero-selection-halo' is generated once per scene and reused. Pulse tween still alpha + scale yoyo (650ms), targeting the Image object so the gradient glows rather than a disc.
1 parent 371aa5a commit 1f5e000

1 file changed

Lines changed: 39 additions & 8 deletions

File tree

client/src/game/entities/HeroSprite.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,32 @@ const WAITING_COLOR = '#FFD700';
3131
const ERROR_COLOR = '#FF4444';
3232
const ERROR_WINDOW_MS = 90 * 1000;
3333

34+
const HALO_TEXTURE_KEY = 'hero-selection-halo';
35+
36+
/**
37+
* Lazily build a soft radial-gradient texture we can reuse as the selection
38+
* halo. Generated once per scene; subsequent callers hit the texture cache.
39+
* The gradient fades white → transparent so the glow blends with the scene
40+
* instead of looking like a flat disc.
41+
*/
42+
function ensureHaloTexture(scene: Phaser.Scene): void {
43+
if (scene.textures.exists(HALO_TEXTURE_KEY)) return;
44+
const size = 128;
45+
const tex = scene.textures.createCanvas(HALO_TEXTURE_KEY, size, size);
46+
if (tex === null) return;
47+
const ctx = tex.getContext();
48+
const cx = size / 2;
49+
const cy = size / 2;
50+
const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, cx);
51+
grad.addColorStop(0.00, 'rgba(255, 255, 255, 0.9)');
52+
grad.addColorStop(0.35, 'rgba(255, 255, 255, 0.45)');
53+
grad.addColorStop(0.70, 'rgba(255, 255, 255, 0.12)');
54+
grad.addColorStop(1.00, 'rgba(255, 255, 255, 0.0)');
55+
ctx.fillStyle = grad;
56+
ctx.fillRect(0, 0, size, size);
57+
tex.refresh();
58+
}
59+
3460
export class HeroSprite {
3561
readonly id: string;
3662
readonly heroClass: HeroClass;
@@ -59,7 +85,7 @@ export class HeroSprite {
5985
private isErrorRecent = false;
6086
private nameBaseColor = '#DDDDDD';
6187
private selectionTween: Phaser.Tweens.Tween | null = null;
62-
private selectionHalo: Phaser.GameObjects.Arc | null = null;
88+
private selectionHalo: Phaser.GameObjects.Image | null = null;
6389

6490
/** Grid base position — used for slot repositioning. */
6591
gridBaseX = 0;
@@ -226,14 +252,19 @@ export class HeroSprite {
226252
this.selectionHalo = null;
227253
}
228254
if (selected) {
229-
const radius = Math.max(this.sprite.displayWidth, this.sprite.displayHeight) * 0.32;
230-
this.selectionHalo = this.scene.add.circle(this._x, this._y, radius, 0xffffff, 0.25);
231-
this.selectionHalo.setDepth(this.sprite.depth - 0.1);
255+
ensureHaloTexture(this.scene);
256+
const diameter = Math.max(this.sprite.displayWidth, this.sprite.displayHeight) * 1.1;
257+
const halo = this.scene.add.image(this._x, this._y, HALO_TEXTURE_KEY);
258+
halo.setDisplaySize(diameter, diameter);
259+
halo.setAlpha(0.35);
260+
halo.setDepth(this.sprite.depth - 0.1);
261+
this.selectionHalo = halo;
232262
this.selectionTween = this.scene.tweens.add({
233-
targets: this.selectionHalo,
234-
alpha: 0.55,
235-
scale: 1.3,
236-
duration: 500,
263+
targets: halo,
264+
alpha: 0.75,
265+
scaleX: halo.scaleX * 1.25,
266+
scaleY: halo.scaleY * 1.25,
267+
duration: 650,
237268
yoyo: true,
238269
repeat: -1,
239270
ease: 'Sine.easeInOut',

0 commit comments

Comments
 (0)