105 lines
2.3 KiB
JavaScript
105 lines
2.3 KiB
JavaScript
/**
|
|
* Explosion.js
|
|
* Simple explosion effect using frame-based animation.
|
|
* Managed via object pool for performance.
|
|
*/
|
|
|
|
class Explosion {
|
|
constructor() {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.alive = false;
|
|
this.size = 0;
|
|
this.maxSize = 30;
|
|
this._timer = 0;
|
|
this._duration = 0.3; // seconds
|
|
this._phase = 0; // 0 to 1
|
|
this._isBig = false; // big explosion for tank destruction
|
|
}
|
|
|
|
/**
|
|
* Initialize the explosion.
|
|
* @param {number} x - Center X.
|
|
* @param {number} y - Center Y.
|
|
* @param {boolean} [isBig=false] - Whether this is a large explosion (tank death).
|
|
*/
|
|
init(x, y, isBig = false) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.alive = true;
|
|
this._timer = 0;
|
|
this._phase = 0;
|
|
this._isBig = isBig;
|
|
this.maxSize = isBig ? 50 : 25;
|
|
this._duration = isBig ? 0.5 : 0.3;
|
|
}
|
|
|
|
/**
|
|
* Update explosion animation.
|
|
* @param {number} dt - Delta time in seconds.
|
|
*/
|
|
update(dt) {
|
|
if (!this.alive) return;
|
|
|
|
this._timer += dt;
|
|
this._phase = this._timer / this._duration;
|
|
|
|
if (this._phase >= 1) {
|
|
this.alive = false;
|
|
return;
|
|
}
|
|
|
|
// Size grows then shrinks
|
|
if (this._phase < 0.4) {
|
|
this.size = this.maxSize * (this._phase / 0.4);
|
|
} else {
|
|
this.size = this.maxSize * (1 - (this._phase - 0.4) / 0.6);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render the explosion.
|
|
* @param {CanvasRenderingContext2D} ctx
|
|
*/
|
|
render(ctx) {
|
|
if (!this.alive) return;
|
|
|
|
ctx.save();
|
|
|
|
const alpha = 1 - this._phase * 0.5;
|
|
ctx.globalAlpha = alpha;
|
|
|
|
// Outer glow
|
|
if (this._isBig) {
|
|
ctx.fillStyle = '#FF4500';
|
|
ctx.beginPath();
|
|
ctx.arc(this.x, this.y, this.size * 1.2, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
}
|
|
|
|
// Main explosion
|
|
ctx.fillStyle = '#FF8C00';
|
|
ctx.beginPath();
|
|
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
// Inner bright core
|
|
ctx.fillStyle = '#FFFF00';
|
|
ctx.beginPath();
|
|
ctx.arc(this.x, this.y, this.size * 0.5, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
// White center flash (early phase only)
|
|
if (this._phase < 0.3) {
|
|
ctx.fillStyle = '#FFFFFF';
|
|
ctx.beginPath();
|
|
ctx.arc(this.x, this.y, this.size * 0.2, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
}
|
|
|
|
ctx.restore();
|
|
}
|
|
}
|
|
|
|
module.exports = Explosion;
|