XGravity/Public/ecma/Fx/HullHitExplosionsFx.ecma.js

134 lines
4.8 KiB
JavaScript

"use strict";
const HullHitExplosionsFx = (function(){
const HullHitExplosionsFx = function(xgravity){
let shockwaves = [];
let particles = [];
this.add = (cell_x, cell_y) => {
if(xgravity.audio){
xgravity.audio.play("hit_explosion");
}
const particles_range = xgravity.settings.get("explosion_particles_range", null, [45, 75]);
const spread_reach = xgravity.settings.get("explosion_particles_spread", null, 11.0);
const base_shockwave_radius = xgravity.settings.get("explosion_shockwave_radius", null, 4.5);
const min_p = Math.min(particles_range[0], particles_range[1]);
const max_p = Math.max(particles_range[0], particles_range[1]);
const count = Math.floor(min_p + Math.random() * (max_p - min_p + 1));
// Onda roja más grande
shockwaves.push({
x : cell_x,
y : cell_y,
radius : 0.4,
max_radius : base_shockwave_radius * 1.15,
speed : 8.0,
angle : Math.random() * Math.PI * 2,
aspect_ratio : 0.42 + (Math.random() * 0.18),
alpha : 1.0,
color_rgb : "239, 68, 68"
});
// Metralla naranja/roja/amarilla
for(let i = 0; i < count; i++){
const angle = Math.random() * Math.PI * 2;
const speed = (Math.random() * spread_reach) + 1.2;
const life = (Math.random() * 0.38) + 0.28;
const rim_rgb = Math.random() > 0.4 ? "239, 68, 68" : (Math.random() > 0.5 ? "249, 115, 22" : "251, 191, 36");
particles.push({
x : cell_x,
y : cell_y,
vx : Math.cos(angle) * speed,
vy : Math.sin(angle) * speed,
size : (Math.random() * 0.16) + 0.08,
life : life,
max_life : life,
core_rgb : "255, 255, 255",
rim_rgb : rim_rgb
});
}
};
this.update = (delta_time) => {
for(let i = shockwaves.length - 1; i >= 0; i--){
const s = shockwaves[i];
s.radius += s.speed * delta_time;
s.alpha = Math.max(0, 1.0 - (s.radius / s.max_radius));
if(s.radius >= s.max_radius){
shockwaves.splice(i, 1);
}
}
for(let i = particles.length - 1; i >= 0; i--){
const p = particles[i];
p.life -= delta_time;
if(p.life <= 0){
particles.splice(i, 1);
continue;
}
p.x += p.vx * delta_time;
p.y += p.vy * delta_time;
p.vx *= 0.93;
p.vy *= 0.93;
}
};
this.render = (ctx, cell_px, cx, cy) => {
for(let i = 0; i < shockwaves.length; i++){
const s = shockwaves[i];
const px = cx + (s.x * cell_px);
const py = cy + (s.y * cell_px);
const r_px = s.radius * cell_px;
ctx.save();
ctx.translate(px, py);
ctx.rotate(s.angle);
ctx.scale(1.0, s.aspect_ratio);
ctx.lineWidth = cell_px * 0.14 * s.alpha;
ctx.strokeStyle = `rgba(${s.color_rgb}, ${s.alpha * 0.85})`;
ctx.beginPath();
ctx.arc(0, 0, r_px, 0, Math.PI * 2);
ctx.stroke();
ctx.lineWidth = cell_px * 0.05 * s.alpha;
ctx.strokeStyle = `rgba(255, 255, 255, ${s.alpha * 0.6})`;
ctx.beginPath();
ctx.arc(0, 0, r_px * 0.82, 0, Math.PI * 2);
ctx.stroke();
ctx.restore();
}
for(let i = 0; i < particles.length; i++){
const p = particles[i];
const px = cx + (p.x * cell_px);
const py = cy + (p.y * cell_px);
const r_px = p.size * cell_px;
const progress = Math.max(0, p.life / p.max_life);
const grad = ctx.createRadialGradient(px, py, 0, px, py, r_px);
grad.addColorStop(0.0, `rgba(${p.core_rgb}, ${progress})`);
grad.addColorStop(0.45, `rgba(${p.rim_rgb}, ${progress * 0.75})`);
grad.addColorStop(1.0, `rgba(${p.rim_rgb}, 0.0)`);
ctx.fillStyle = grad;
ctx.beginPath();
ctx.arc(px, py, r_px, 0, Math.PI * 2);
ctx.fill();
}
};
this.reset = () => {
shockwaves = [];
particles = [];
};
};
return HullHitExplosionsFx;
})();