Files
OpenFrontIO/src/client/graphics/fx/SpriteFx.ts
T
DevelopingTomandGitHub 648ae1943f Christmas Themed FX (#2624)
## Description:

### Santa:
- spawn randomly on the map every minute:


![santa_is_coming](https://github.com/user-attachments/assets/0c40f983-7c5e-4fd9-93cd-5601008cb2ef)

### Nuke changes:
- Atom: small gift
- Hydro: big gift
- MIRV: shooting star


![all_christmas_nukes](https://github.com/user-attachments/assets/db80d765-6292-44e0-a5a3-fe08c0516993)

### Nuke fallout FX:
- melting snowman
- happy elves
- elves needing assistance


![christmastroph](https://github.com/user-attachments/assets/92270357-a0f6-43bf-9b95-cc5b2427a542)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2025-12-15 20:24:23 -08:00

98 lines
2.5 KiB
TypeScript

import { Theme } from "../../../core/configuration/Config";
import { PlayerView } from "../../../core/game/GameView";
import { AnimatedSprite } from "../AnimatedSprite";
import { AnimatedSpriteLoader } from "../AnimatedSpriteLoader";
import { Fx, FxType } from "./Fx";
function fadeInOut(
t: number,
fadeIn: number = 0.3,
fadeOut: number = 0.7,
): number {
if (t < fadeIn) {
const f = t / fadeIn; // Map to [0, 1]
return f * f;
} else if (t < fadeOut) {
return 1;
} else {
const f = (t - fadeOut) / (1 - fadeOut); // Map to [0, 1]
return 1 - f * f;
}
}
/**
* Fade in/out another FX
*/
export class FadeFx implements Fx {
constructor(
private fxToFade: SpriteFx,
private fadeIn: number,
private fadeOut: number,
) {}
renderTick(duration: number, ctx: CanvasRenderingContext2D): boolean {
const t = this.fxToFade.getElapsedTime() / this.fxToFade.getDuration();
ctx.save();
ctx.globalAlpha = fadeInOut(t, this.fadeIn, this.fadeOut);
const result = this.fxToFade.renderTick(duration, ctx);
ctx.restore();
return result;
}
}
/**
* Animated sprite. Can be colored if provided an owner/theme
*/
export class SpriteFx implements Fx {
protected animatedSprite: AnimatedSprite | null;
protected elapsedTime = 0;
protected duration: number;
protected waitToTheEnd = false;
constructor(
animatedSpriteLoader: AnimatedSpriteLoader,
protected x: number,
protected y: number,
fxType: FxType,
duration?: number,
owner?: PlayerView,
theme?: Theme,
) {
this.animatedSprite = animatedSpriteLoader.createAnimatedSprite(
fxType,
owner,
theme,
);
if (!this.animatedSprite) {
console.error("Could not load animated sprite", fxType);
} else {
this.waitToTheEnd = duration ? true : false;
this.duration = duration ?? this.animatedSprite.lifeTime() ?? 1000;
}
}
public setPosition(x: number, y: number): void {
this.x = x;
this.y = y;
}
renderTick(frameTime: number, ctx: CanvasRenderingContext2D): boolean {
if (!this.animatedSprite) return false;
this.elapsedTime += frameTime;
if (this.elapsedTime >= this.duration) return false;
if (!this.animatedSprite.isActive() && !this.waitToTheEnd) return false;
this.animatedSprite.update(frameTime);
this.animatedSprite.draw(ctx, this.x, this.y);
return true;
}
getElapsedTime(): number {
return this.elapsedTime;
}
getDuration(): number {
return this.duration;
}
}