1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
use glam::Vec2;
use rand::random_range;
use crate::sim::{
cell::{
cell::Cell,
materials::{MaterialId, fire::FireCellView},
},
cell_sim::world::World,
particle_sim::{ParticleManager, particle::Particle},
rb_sim::RbSimManager,
};
pub fn apply_explosion(
centre: Vec2,
radius: i32,
force_offset: Vec2,
force_multiplier: f32,
next_seqno: u64,
particle_manager: &mut ParticleManager,
world: &mut World,
rbsm: &mut RbSimManager,
) {
let get_vel = |pos: Vec2| {
let d = pos.distance(centre);
if d < 0.001 {
return Vec2::ZERO;
}
let dir = (pos - centre) / d;
let falloff = 1.0 - (d / radius as f32);
return (force_offset + dir) * force_multiplier * random_range(0.5..1.5) * falloff;
};
// cell grid
for x in -radius..radius {
for y in -radius..radius {
if x.pow(2) + y.pow(2) < radius.pow(2) {
// if there's a cell, convert it to a particle
let pos = Vec2::new(centre.x + x as f32, centre.y + y as f32);
let ipos = pos.round().as_ivec2();
if let Some(cell) = world.get_cell_from_game_position(ipos.x, ipos.y) {
let mut fire = Cell::from_material(MaterialId::Fire);
fire.set_ticks_lived(300);
fire.match_parity(next_seqno);
if cell.material == MaterialId::Void && random_range(0.0..1.0) > 0.5 {
if random_range(0.0..1.0) > 0.1 {
world.set_cell_from_game_position(ipos.x, ipos.y, fire, false);
} else {
let vel = get_vel(pos);
particle_manager.particles.push(Particle::new(
pos,
vel,
MaterialId::Fire,
1.0,
));
}
} else {
world.set_cell_from_game_position(ipos.x, ipos.y, fire, false);
if random_range(0.0..1.0) > 0.6 {
let vel = get_vel(pos);
particle_manager.particles.push(Particle::new(
pos,
vel,
cell.material,
5.0,
));
}
}
}
}
}
}
// rigidbodies
}
|