summaryrefslogtreecommitdiff
path: root/src/sim/lib/force.rs
blob: 39b7904c0107fffc1553e253cace60df91c2e0c9 (plain)
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::{
    content::materials::{MaterialForm, MaterialId, fire::FireCellView},
    sim::{cell::cell::Cell, particle_manager::particle::Particle, sim_manager::SimCtx},
};

pub fn apply_explosion(
    ctx: &mut SimCtx,
    centre: Vec2,
    radius: i32,
    force_offset: Vec2,
    force_multiplier: f32,
) {
    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) = ctx.cell_manager.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(ctx.cell_manager.seqno);

                    if cell.material == MaterialId::Void && random_range(0.0..1.0) > 0.5 {
                        if random_range(0.0..1.0) > 0.1 {
                            ctx.cell_manager
                                .set_cell_from_game_position(ipos.x, ipos.y, fire, false);
                        } else {
                            let vel = get_vel(pos);
                            ctx.particle_manager.particles.push(Particle::new(
                                pos,
                                vel,
                                MaterialId::Fire,
                                1.0,
                            ));
                        }
                    } else if [
                        MaterialForm::Solid,
                        MaterialForm::Liquid,
                        MaterialForm::Powder,
                    ]
                    .contains(&cell.material.def().form)
                    {
                        ctx.cell_manager
                            .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);
                            ctx.particle_manager.particles.push(Particle::new(
                                pos,
                                vel,
                                cell.material,
                                5.0,
                            ));
                        }
                    }
                }
            }
        }
    }

    // rigidbodies
}