healing particle effect
This commit is contained in:
BIN
assets/models/medic_particle.glb
Normal file
BIN
assets/models/medic_particle.glb
Normal file
Binary file not shown.
@@ -6,7 +6,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
struct Healing(Entity);
|
||||
pub struct Healing(pub Entity);
|
||||
|
||||
#[derive(Event, Debug)]
|
||||
pub enum HealingStateChanged {
|
||||
|
||||
@@ -4,6 +4,8 @@ mod healing;
|
||||
mod missile;
|
||||
mod thrown;
|
||||
|
||||
pub use healing::Healing;
|
||||
|
||||
use crate::{
|
||||
GameState,
|
||||
aim::AimTarget,
|
||||
|
||||
99
src/heal_effect.rs
Normal file
99
src/heal_effect.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use crate::{
|
||||
GameState, abilities::Healing, loading_assets::GameAssets, utils::billboards::Billboard,
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
use rand::{Rng, thread_rng};
|
||||
|
||||
#[derive(Component, Default)]
|
||||
#[require(Transform, InheritedVisibility)]
|
||||
struct HealParticleEffect {
|
||||
next_spawn: f32,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct HealParticle {
|
||||
start_scale: f32,
|
||||
end_scale: f32,
|
||||
start_pos: Vec3,
|
||||
end_pos: Vec3,
|
||||
start_time: f32,
|
||||
life_time: f32,
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(
|
||||
Update,
|
||||
(on_added, update_effects, update_particles).run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
}
|
||||
|
||||
fn on_added(mut cmds: Commands, query: Query<&Healing, Added<Healing>>) {
|
||||
for healing in query.iter() {
|
||||
cmds.entity(healing.0).insert((
|
||||
Name::new("heal-particle-effect"),
|
||||
HealParticleEffect::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn update_effects(
|
||||
mut cmds: Commands,
|
||||
mut query: Query<(&mut HealParticleEffect, Entity)>,
|
||||
time: Res<Time>,
|
||||
assets: Res<GameAssets>,
|
||||
) {
|
||||
const DISTANCE: f32 = 4.;
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let now = time.elapsed_secs();
|
||||
for (mut effect, e) in query.iter_mut() {
|
||||
if effect.next_spawn < now {
|
||||
let start_pos = Vec3::new(
|
||||
rng.gen_range(-DISTANCE..DISTANCE),
|
||||
2.,
|
||||
rng.gen_range(-DISTANCE..DISTANCE),
|
||||
);
|
||||
let max_distance = start_pos.length().max(0.8);
|
||||
let end_pos =
|
||||
start_pos + (start_pos.normalize() * -1.) * rng.gen_range(0.5..max_distance);
|
||||
let start_scale = rng.gen_range(0.7..1.0);
|
||||
let end_scale = rng.gen_range(0.1..start_scale);
|
||||
|
||||
cmds.entity(e).with_child((
|
||||
Name::new("heal-particle"),
|
||||
SceneRoot(assets.mesh_heal_particle.clone()),
|
||||
Billboard,
|
||||
Transform::from_translation(start_pos),
|
||||
HealParticle {
|
||||
start_scale,
|
||||
end_scale,
|
||||
start_pos,
|
||||
end_pos,
|
||||
start_time: now,
|
||||
life_time: rng.gen_range(0.3..1.0),
|
||||
},
|
||||
));
|
||||
|
||||
effect.next_spawn = now + rng.gen_range(0.1..0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_particles(
|
||||
mut cmds: Commands,
|
||||
mut query: Query<(&mut Transform, &HealParticle, Entity)>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
for (mut transform, particle, e) in query.iter_mut() {
|
||||
if particle.start_time + particle.life_time < time.elapsed_secs() {
|
||||
cmds.entity(e).despawn();
|
||||
continue;
|
||||
}
|
||||
|
||||
let t = (time.elapsed_secs() - particle.start_time) / particle.life_time;
|
||||
|
||||
// info!("particle[{e:?}] t: {t}");
|
||||
transform.translation = particle.start_pos.lerp(particle.end_pos, t);
|
||||
transform.scale = Vec3::splat(particle.start_scale.lerp(particle.end_scale, t));
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,9 @@ pub struct GameAssets {
|
||||
#[asset(path = "models/cash.glb#Scene0")]
|
||||
pub mesh_cash: Handle<Scene>,
|
||||
|
||||
#[asset(path = "models/medic_particle.glb#Scene0")]
|
||||
pub mesh_heal_particle: Handle<Scene>,
|
||||
|
||||
#[asset(path = "models/projectiles", collection(mapped, typed))]
|
||||
pub projectiles: HashMap<AssetFileName, Handle<Gltf>>,
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ mod head;
|
||||
mod head_drop;
|
||||
mod heads;
|
||||
mod heads_database;
|
||||
mod heal_effect;
|
||||
mod hitpoints;
|
||||
mod keys;
|
||||
mod loading_assets;
|
||||
@@ -165,6 +166,7 @@ fn main() {
|
||||
app.add_plugins(water::plugin);
|
||||
app.add_plugins(head_drop::plugin);
|
||||
app.add_plugins(trail::plugin);
|
||||
app.add_plugins(heal_effect::plugin);
|
||||
|
||||
app.init_state::<GameState>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user