diff --git a/assets/textures/fx/impact.png b/assets/textures/fx/impact.png new file mode 100644 index 0000000..bcdfe43 Binary files /dev/null and b/assets/textures/fx/impact.png differ diff --git a/src/billboards.rs b/src/billboards.rs index 71b9ed2..ccd4ebd 100644 --- a/src/billboards.rs +++ b/src/billboards.rs @@ -11,7 +11,7 @@ pub fn plugin(app: &mut App) { } app.register_type::(); - app.add_systems(Update, face_camera); + app.add_systems(Update, (face_camera, face_camera_no_parent)); } fn face_camera( @@ -36,3 +36,13 @@ fn face_camera( transform.look_at(target.translation, Vec3::Y); } } + +fn face_camera_no_parent( + cam_query: Query<&GlobalTransform, With>, + mut query: Query<&mut Transform, (With, Without, Without)>, +) { + let cam_transform = cam_query.single(); + for mut transform in query.iter_mut() { + transform.look_at(cam_transform.translation(), Vec3::Y); + } +} diff --git a/src/camera.rs b/src/camera.rs index b68b5c2..0d2ee83 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -59,7 +59,7 @@ pub fn plugin(app: &mut App) { fn startup(mut commands: Commands) { commands.spawn(( Camera3d::default(), - MainCamera::new(Vec3::new(0., 2., -12.)), + MainCamera::new(Vec3::new(0., 2.5, -13.)), CameraRotation(0.), )); } diff --git a/src/main.rs b/src/main.rs index fae6c7b..fdfbb06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ use bevy::prelude::*; use bevy::render::view::ColorGrading; use bevy::scene::SceneInstanceReady; use bevy_polyline::PolylinePlugin; +use bevy_sprite3d::Sprite3dPlugin; use bevy_trenchbroom::prelude::*; use control::controller::CharacterControllerPlugin; use physics_layers::GameLayer; @@ -65,6 +66,7 @@ fn main() { app.add_plugins(PhysicsPlugins::default()); app.add_plugins(CharacterControllerPlugin); app.add_plugins(PolylinePlugin); + app.add_plugins(Sprite3dPlugin); app.add_plugins(TrenchBroomPlugin(TrenchBroomConfig::new("hedz"))); #[cfg(feature = "dbg")] diff --git a/src/shooting.rs b/src/shooting.rs index 42eb52b..83d02c2 100644 --- a/src/shooting.rs +++ b/src/shooting.rs @@ -1,5 +1,6 @@ use crate::{ aim::AimState, + billboards::Billboard, npc::Hit, physics_layers::GameLayer, player::{Player, PlayerRig}, @@ -9,8 +10,9 @@ use crate::{ use avian3d::prelude::{ Collider, CollisionLayers, CollisionStarted, LayerMask, PhysicsLayer, Sensor, }; -use bevy::prelude::*; +use bevy::{pbr::NotShadowCaster, prelude::*}; use bevy_polyline::prelude::*; +use bevy_sprite3d::{Sprite3d, Sprite3dBuilder, Sprite3dParams}; use std::f32::consts::PI; #[derive(Component)] @@ -26,11 +28,40 @@ pub enum TriggerState { Inactive, } +#[derive(Resource)] +struct ShotAssets { + image: Handle, + layout: Handle, +} + +//TODO: give its own plugin +#[derive(Component, Deref, DerefMut)] +struct AnimationTimer(Timer); + pub fn plugin(app: &mut App) { - app.add_systems(Update, (update, shot_collision, enemy_hit, timeout)); + app.add_systems(Startup, setup); + app.add_systems( + Update, + (update, shot_collision, enemy_hit, timeout, animate_sprite), + ); app.add_observer(on_trigger_state); } +fn setup( + mut commands: Commands, + asset_server: Res, + mut sprite_params: Sprite3dParams, +) { + let image = asset_server.load("textures/fx/impact.png"); + let layout = TextureAtlasLayout::from_grid(UVec2::splat(256), 7, 6, None, None); + let texture_atlas_layout = sprite_params.atlas_layouts.add(layout); + + commands.insert_resource(ShotAssets { + image, + layout: texture_atlas_layout, + }); +} + fn on_trigger_state( trigger: Trigger, mut commands: Commands, @@ -75,6 +106,7 @@ fn on_trigger_state( Collider::capsule_endpoints(0.5, Vec3::new(0., 0., 0.), Vec3::new(0., 0., -3.)), CollisionLayers::new(LayerMask(GameLayer::Projectile.to_bits()), LayerMask::ALL), Sensor, + Visibility::default(), t, )) .with_child(PolylineBundle { @@ -129,11 +161,33 @@ fn enemy_hit( } } +fn animate_sprite( + mut commands: Commands, + time: Res