~starkingdoms/starkingdoms

ref: aa9bcf7200f6a8ce6ed78b392414cbffad896788 starkingdoms/crates/unified/src/particle_editor/spawn.rs -rw-r--r-- 3.4 KiB
aa9bcf72 — ghostly_zsh feat: starguide dragging 18 days ago
                                                                                
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use std::time::Duration;
use avian2d::prelude::*;
use crate::prelude::*;

use crate::{
    particle_editor::ecs::{CircleMesh, LifetimeTimer, ParentEffect, Particle, SpawnDelayTimer},
    particles::ParticleEffect,
};

pub fn spawn_plugin(app: &mut App) {
    app.add_systems(Update, spawn_particles);
    app.add_systems(Update, lifetime_particles);
}

fn spawn_particles(
    mut commands: Commands,
    particle_effects: Query<(&Transform, &ParticleEffect, &mut SpawnDelayTimer)>,
    time: ResMut<Time>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    for (transform, effect, mut delay_timer) in particle_effects {
        delay_timer.0.tick(time.delta());
        if delay_timer.0.just_finished() {
            for _ in 0..effect.particles_in_batch.sample(&mut rand::rng()) {
                let circle = CircleMesh(
                    meshes.add(Circle::new(1.0)),
                    materials.add(
                        effect
                            .color
                            .sample(effect.color.clamp_time(0.0).unwrap())
                            .unwrap(),
                    ),
                );
                commands.spawn((
                    RigidBody::Dynamic,
                    Particle,
                    transform.with_scale(Vec3::splat(
                        effect
                            .scale
                            .sample(effect.scale.clamp_time(0.0).unwrap())
                            .unwrap(),
                    )),
                    Mesh2d(circle.0.clone()),
                    MeshMaterial2d(circle.1.clone()),
                    LinearVelocity(effect.initial_linear_velocity.sample(&mut rand::rng())),
                    AngularVelocity(effect.initial_angular_velocity.sample(&mut rand::rng())),
                    LifetimeTimer(Timer::from_seconds(
                        effect.lifetime_seconds.sample(&mut rand::rng()),
                        TimerMode::Once,
                    )),
                    circle,
                    ParentEffect(effect.clone()),
                ));
            }
            delay_timer.0.set_duration(Duration::from_secs_f32(
                effect.batch_spawn_delay_seconds.sample(&mut rand::rng()),
            ));
            delay_timer.0.reset();
        }
    }
}

fn lifetime_particles(
    mut commands: Commands,
    mut particles: Query<
        (
            Entity,
            &mut LifetimeTimer,
            &mut Transform,
            &CircleMesh,
            &ParentEffect,
        ),
        With<Particle>,
    >,
    time: ResMut<Time>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    for (entity, mut timer, mut transform, circle, parent) in &mut particles {
        timer.0.tick(time.delta());
        transform.scale = Vec3::splat(
            parent
                .0
                .scale
                .sample(parent.0.scale.clamp_time(timer.0.elapsed_secs()).unwrap())
                .unwrap(),
        );
        materials.get_mut(&circle.1).unwrap().color = parent
            .0
            .color
            .sample(parent.0.color.clamp_time(timer.0.elapsed_secs()).unwrap())
            .unwrap();
        if timer.0.just_finished() {
            commands.entity(entity).despawn();
            meshes.remove(&circle.0);
            materials.remove(&circle.1);
        }
    }
}