134 lines
4.8 KiB
JavaScript
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;
|
|
})(); |