initial commit

This commit is contained in:
armel committed 2026-09-07 20:37:40 +02:00
commit e8c3f9862a
193 files changed
+29795

No files matched your search

+231
View File
@@ -0,0 +1,231 @@
const MAX_RINGS = 40;
const MAX_GLOWS = 60;
const MAX_STREAKS = 90;
const MAX_ARCS = 28;
const easeOut = (t) => 1 - (1 - t) * (1 - t);
export class Effects {
constructor() {
this.rings = [];
this.glows = [];
this.streaks = [];
this.arcs = [];
}
ring(x, y, {
endRadius = 140,
width = 5,
life = 0.5,
color = [1, 1, 1, 1],
additive = true,
} = {}) {
if (this.rings.length >= MAX_RINGS) this.rings.shift();
this.rings.push({
x, y,
radius: endRadius * 0.12,
endRadius,
width,
life,
maxLife: life,
color,
additive,
});
}
glow(x, y, {
radius = 90,
life = 0.35,
color = [1, 1, 1, 1],
additive = true,
} = {}) {
if (this.glows.length >= MAX_GLOWS) this.glows.shift();
this.glows.push({
x, y,
radius: radius * 0.2,
endRadius: radius,
life,
maxLife: life,
color,
additive,
});
}
streak(x, y, angle, length, {
width = 3,
life = 0.25,
fade = true,
color = [1, 1, 1, 1],
additive = true,
tail = 0.7,
} = {}) {
if (this.streaks.length >= MAX_STREAKS) this.streaks.shift();
this.streaks.push({
x: x - Math.cos(angle) * length * tail,
y: y - Math.sin(angle) * length * tail,
angle,
length,
width,
life,
maxLife: life,
fade,
color,
additive,
tail,
});
}
arc(x1, y1, x2, y2, {
segments = 8,
width = 3,
life = 0.3,
color = [1, 1, 1, 1],
jitter = 26,
additive = true,
} = {}) {
if (this.arcs.length >= MAX_ARCS) this.arcs.shift();
this.arcs.push({
x1, y1, x2, y2,
segments,
width,
life,
maxLife: life,
color,
jitter,
additive,
seed: Math.random() * 100,
});
}
update(dt) {
const tick = (list) => {
for (let i = list.length - 1; i >= 0; i -= 1) {
list[i].life -= dt;
if (list[i].life <= 0) list.splice(i, 1);
}
};
tick(this.rings);
tick(this.glows);
tick(this.streaks);
tick(this.arcs);
}
draw(renderer) {
for (const list of [this.glows, this.rings, this.streaks, this.arcs]) {
const additive = list.filter((effect) => effect.additive);
const normal = list.filter((effect) => !effect.additive);
if (additive.length > 0) renderer.setBlendMode('additive');
for (const effect of additive) this._drawEffect(renderer, effect);
if (additive.length > 0) renderer.setBlendMode('normal');
for (const effect of normal) this._drawEffect(renderer, effect);
}
}
_drawEffect(renderer, effect) {
const t = 1 - effect.life / effect.maxLife;
const alpha = effect.life / effect.maxLife;
if (effect.x1 !== undefined) {
this._drawArc(renderer, effect, t, alpha);
} else if (effect.angle !== undefined) {
this._drawStreak(renderer, effect, t, alpha);
} else if (effect.width !== undefined) {
this._drawRing(renderer, effect, t, alpha);
} else {
this._drawGlow(renderer, effect, t, alpha);
}
}
_drawGlow(renderer, effect, t, alpha) {
const radius = effect.radius + (effect.endRadius - effect.radius) * easeOut(t);
renderer.drawTexture(
renderer.glowTexture,
effect.x - radius,
effect.y - radius,
radius * 2,
radius * 2,
[
effect.color[0],
effect.color[1],
effect.color[2],
effect.color[3] * alpha,
],
);
}
_drawRing(renderer, effect, t, alpha) {
const radius = effect.radius + (effect.endRadius - effect.radius) * easeOut(t);
const fade = Math.min(1, alpha * 1.3);
renderer.drawTexture(
renderer.ringTexture,
effect.x - radius,
effect.y - radius,
radius * 2,
radius * 2,
[
effect.color[0],
effect.color[1],
effect.color[2],
Math.max(0, effect.color[3] * fade),
],
);
}
_drawStreak(renderer, effect, t, alpha) {
const progress = easeOut(t);
const len = effect.length * (1 - progress * (1 - effect.tail));
const fade = effect.fade ? alpha : 1;
renderer.drawTexture(
renderer.glowTexture,
effect.x,
effect.y,
len,
effect.width,
[
effect.color[0],
effect.color[1],
effect.color[2],
effect.color[3] * fade,
],
effect.angle,
);
}
_drawArc(renderer, effect, t, alpha) {
const { x1, y1, x2, y2, segments, width, jitter, seed, color } = effect;
const wobble = 0.45 + 0.55 * Math.abs(Math.sin(seed + t * 34));
const amp = jitter * alpha * wobble;
let prevX = x1;
let prevY = y1;
for (let i = 1; i <= segments; i += 1) {
const u = i / segments;
const edge = (i === segments) ? 0 : 1;
const px = x1 + (x2 - x1) * u + (Math.random() - 0.5) * 2 * amp * edge;
const py = y1 + (y2 - y1) * u + (Math.random() - 0.5) * 2 * amp * edge;
const len = Math.hypot(px - prevX, py - prevY);
if (len > 0) {
renderer.drawTexture(
renderer.whiteTexture,
prevX,
prevY,
len,
width,
[color[0], color[1], color[2], color[3] * alpha],
Math.atan2(py - prevY, px - prevX),
);
}
prevX = px;
prevY = py;
}
}
clear() {
this.rings.length = 0;
this.glows.length = 0;
this.streaks.length = 0;
this.arcs.length = 0;
}
}