use different head drop meshes
This commit is contained in:
BIN
assets/models/head_drops/none.glb
Normal file
BIN
assets/models/head_drops/none.glb
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets,
|
GameState, billboards::Billboard, global_observer, heads_database::HeadsDatabase,
|
||||||
physics_layers::GameLayer, player::Player, sounds::PlaySound,
|
loading_assets::HeadDropAssets, physics_layers::GameLayer, player::Player, sounds::PlaySound,
|
||||||
squish_animation::SquishAnimation, tb_entities::SecretHead,
|
squish_animation::SquishAnimation, tb_entities::SecretHead,
|
||||||
};
|
};
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::*;
|
||||||
@@ -8,7 +8,29 @@ use bevy::prelude::*;
|
|||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
#[derive(Event, Reflect)]
|
#[derive(Event, Reflect)]
|
||||||
pub struct HeadDrops(pub Vec3, pub usize);
|
pub struct HeadDrops {
|
||||||
|
pos: Vec3,
|
||||||
|
head_id: usize,
|
||||||
|
impulse: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeadDrops {
|
||||||
|
pub fn new(pos: Vec3, head_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
pos,
|
||||||
|
head_id,
|
||||||
|
impulse: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_static(pos: Vec3, head_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
pos,
|
||||||
|
head_id,
|
||||||
|
impulse: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect)]
|
#[derive(Component, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
@@ -28,63 +50,65 @@ pub fn plugin(app: &mut App) {
|
|||||||
global_observer!(app, on_head_drop);
|
global_observer!(app, on_head_drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn(
|
fn spawn(mut commands: Commands, query: Query<(Entity, &GlobalTransform, &SecretHead)>) {
|
||||||
mut commands: Commands,
|
|
||||||
query: Query<(Entity, &GlobalTransform, &SecretHead)>,
|
|
||||||
assets: Res<GameAssets>,
|
|
||||||
) {
|
|
||||||
for (e, t, head) in query {
|
for (e, t, head) in query {
|
||||||
commands
|
commands.trigger(HeadDrops::new_static(
|
||||||
.spawn((
|
t.translation() + Vec3::new(0., 2., 0.),
|
||||||
Name::new("headdrop"),
|
head.head_id,
|
||||||
SecretHeadMarker,
|
));
|
||||||
HeadDrop(head.head_id),
|
|
||||||
Transform::from_translation(t.translation() + Vec3::new(0., 2., 0.)),
|
|
||||||
Visibility::default(),
|
|
||||||
Collider::sphere(1.5),
|
|
||||||
LockedAxes::ROTATION_LOCKED,
|
|
||||||
RigidBody::Dynamic,
|
|
||||||
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
|
|
||||||
CollisionEventsEnabled,
|
|
||||||
Restitution::new(0.6),
|
|
||||||
))
|
|
||||||
.with_child((
|
|
||||||
Billboard,
|
|
||||||
SquishAnimation(2.6),
|
|
||||||
SceneRoot(assets.mesh_head_drop.clone()),
|
|
||||||
));
|
|
||||||
|
|
||||||
commands.entity(e).despawn();
|
commands.entity(e).despawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_head_drop(trigger: Trigger<HeadDrops>, mut commands: Commands, assets: Res<GameAssets>) {
|
fn on_head_drop(
|
||||||
let HeadDrops(position, id) = trigger.event();
|
trigger: Trigger<HeadDrops>,
|
||||||
|
mut commands: Commands,
|
||||||
|
assets: Res<HeadDropAssets>,
|
||||||
|
heads_db: Res<HeadsDatabase>,
|
||||||
|
gltf_assets: Res<Assets<Gltf>>,
|
||||||
|
) -> Result<(), BevyError> {
|
||||||
|
let drop = trigger.event();
|
||||||
|
|
||||||
let angle = rand::random::<f32>() * PI * 2.;
|
let angle = rand::random::<f32>() * PI * 2.;
|
||||||
let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize();
|
let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize();
|
||||||
|
|
||||||
commands.trigger(PlaySound::HeadDrop);
|
if drop.impulse {
|
||||||
|
commands.trigger(PlaySound::HeadDrop);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ability = format!("{:?}.glb", heads_db.head_stats(drop.head_id).ability).to_lowercase();
|
||||||
|
let mesh = if let Some(handle) = assets.meshes.get(ability.as_str()) {
|
||||||
|
gltf_assets.get(handle)
|
||||||
|
} else {
|
||||||
|
gltf_assets.get(&assets.meshes["none.glb"])
|
||||||
|
}
|
||||||
|
.ok_or_else(|| "asset not found")?;
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Name::new("headdrop"),
|
Name::new("headdrop"),
|
||||||
HeadDrop(*id),
|
HeadDrop(drop.head_id),
|
||||||
Transform::from_translation(*position),
|
Transform::from_translation(drop.pos),
|
||||||
Visibility::default(),
|
Visibility::default(),
|
||||||
Collider::sphere(1.5),
|
Collider::sphere(1.5),
|
||||||
ExternalImpulse::new(spawn_dir * 180.).with_persistence(false),
|
|
||||||
LockedAxes::ROTATION_LOCKED,
|
LockedAxes::ROTATION_LOCKED,
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
|
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
|
||||||
CollisionEventsEnabled,
|
CollisionEventsEnabled,
|
||||||
Restitution::new(0.6),
|
Restitution::new(0.6),
|
||||||
))
|
))
|
||||||
|
.insert_if(
|
||||||
|
ExternalImpulse::new(spawn_dir * 180.).with_persistence(false),
|
||||||
|
|| drop.impulse,
|
||||||
|
)
|
||||||
.with_child((
|
.with_child((
|
||||||
Billboard,
|
Billboard,
|
||||||
SquishAnimation(2.6),
|
SquishAnimation(2.6),
|
||||||
SceneRoot(assets.mesh_head_drop.clone()),
|
SceneRoot(mesh.scenes[0].clone()),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_head(
|
fn collect_head(
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ struct HeadsAssets {
|
|||||||
heads: Handle<HeadDatabaseAsset>,
|
heads: Handle<HeadDatabaseAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(AssetCollection, Resource)]
|
||||||
|
pub struct HeadDropAssets {
|
||||||
|
#[asset(path = "models/head_drops", collection(mapped, typed))]
|
||||||
|
pub meshes: HashMap<AssetFileName, Handle<Gltf>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(AssetCollection, Resource)]
|
#[derive(AssetCollection, Resource)]
|
||||||
pub struct UIAssets {
|
pub struct UIAssets {
|
||||||
#[asset(path = "font.ttf")]
|
#[asset(path = "font.ttf")]
|
||||||
@@ -93,9 +99,6 @@ pub struct GameAssets {
|
|||||||
#[asset(path = "models/key.glb#Scene0")]
|
#[asset(path = "models/key.glb#Scene0")]
|
||||||
pub mesh_key: Handle<Scene>,
|
pub mesh_key: Handle<Scene>,
|
||||||
|
|
||||||
#[asset(path = "models/head_drop.glb#Scene0")]
|
|
||||||
pub mesh_head_drop: Handle<Scene>,
|
|
||||||
|
|
||||||
#[asset(path = "models/spawn.glb#Scene0")]
|
#[asset(path = "models/spawn.glb#Scene0")]
|
||||||
pub mesh_spawn: Handle<Scene>,
|
pub mesh_spawn: Handle<Scene>,
|
||||||
|
|
||||||
@@ -122,6 +125,7 @@ impl Plugin for LoadingPlugin {
|
|||||||
.load_collection::<AudioAssets>()
|
.load_collection::<AudioAssets>()
|
||||||
.load_collection::<GameAssets>()
|
.load_collection::<GameAssets>()
|
||||||
.load_collection::<HeadsAssets>()
|
.load_collection::<HeadsAssets>()
|
||||||
|
.load_collection::<HeadDropAssets>()
|
||||||
.load_collection::<UIAssets>(),
|
.load_collection::<UIAssets>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ fn on_kill(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.trigger(HeadDrops(transform.translation, head.0));
|
commands.trigger(HeadDrops::new(transform.translation, head.0));
|
||||||
|
|
||||||
commands.entity(trigger.target()).despawn();
|
commands.entity(trigger.target()).despawn();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user