Files
HEDZReloaded/src/animation.rs
2025-06-25 17:17:21 +02:00

181 lines
5.4 KiB
Rust

use crate::{
GameState, character::CharacterAnimations, head::ActiveHead, heads_database::HeadsDatabase,
};
use bevy::{animation::RepeatAnimation, ecs::query::QueryData, prelude::*};
use std::time::Duration;
pub fn plugin(app: &mut App) {
app.register_type::<AnimationFlags>();
app.add_systems(
Update,
update_animation.run_if(in_state(GameState::Playing)),
);
}
#[derive(Component, Default, Reflect)]
#[reflect(Component)]
pub struct AnimationFlags {
pub any_direction: bool,
pub jumping: bool,
pub just_jumped: bool,
pub shooting: bool,
pub restart_shooting: bool,
pub hit: bool,
}
#[derive(QueryData)]
#[query_data(mutable)]
pub struct AnimationController {
pub transitions: &'static mut AnimationTransitions,
pub player: &'static mut AnimationPlayer,
}
impl AnimationController {
pub fn play_inner(
player: &mut AnimationPlayer,
transitions: &mut AnimationTransitions,
animation: AnimationNodeIndex,
transition: Duration,
repeat: RepeatAnimation,
) {
transitions
.play(player, animation, transition)
.set_repeat(repeat);
}
}
impl AnimationControllerItem<'_> {
pub fn play(
&mut self,
animation: AnimationNodeIndex,
transition: Duration,
repeat: RepeatAnimation,
) {
AnimationController::play_inner(
&mut self.player,
&mut self.transitions,
animation,
transition,
repeat,
);
}
pub fn is_playing(&self, index: AnimationNodeIndex) -> bool {
self.player.is_playing_animation(index)
}
}
const DEFAULT_TRANSITION_DURATION: Duration = Duration::ZERO;
fn update_animation(
mut animated: Query<(
AnimationController,
&CharacterAnimations,
&mut AnimationFlags,
)>,
character: Query<&ActiveHead>,
headdb: Res<HeadsDatabase>,
) {
for (mut controller, anims, mut flags) in animated.iter_mut() {
let head = character.get(anims.of_character).unwrap();
let head = headdb.head_stats(head.0);
let is_playing_shoot = anims.shoot.is_some()
&& controller.is_playing(anims.shoot.unwrap())
&& !controller
.player
.animation(anims.shoot.unwrap())
.unwrap()
.is_finished();
let is_playing_run_shoot = anims.run_shoot.is_some()
&& controller.is_playing(anims.run_shoot.unwrap())
&& !controller
.player
.animation(anims.run_shoot.unwrap())
.unwrap()
.is_finished();
let wait_for_shoot = !head.interrupt_shoot && (is_playing_shoot || is_playing_run_shoot);
if wait_for_shoot {
return;
} else if flags.shooting && flags.any_direction && anims.run_shoot.is_some() {
if !controller.is_playing(anims.run_shoot.unwrap()) {
controller.play(
anims.run_shoot.unwrap(),
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Never,
);
}
if controller
.player
.animation(anims.run_shoot.unwrap())
.unwrap()
.is_finished()
|| flags.restart_shooting
{
controller
.player
.animation_mut(anims.run_shoot.unwrap())
.unwrap()
.replay();
flags.restart_shooting = false;
}
} else if flags.shooting && anims.shoot.is_some() {
if !controller.is_playing(anims.shoot.unwrap()) {
controller.play(
anims.shoot.unwrap(),
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Never,
);
}
if controller
.player
.animation(anims.shoot.unwrap())
.unwrap()
.is_finished()
|| flags.restart_shooting
{
controller
.player
.animation_mut(anims.shoot.unwrap())
.unwrap()
.replay();
flags.restart_shooting = false;
}
} else if flags.hit {
if !controller.is_playing(anims.hit) {
controller.play(
anims.hit,
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Never,
);
}
} else if flags.jumping {
if !controller.is_playing(anims.jump) || flags.just_jumped {
controller.play(
anims.jump,
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Never,
);
flags.just_jumped = false;
}
} else if flags.any_direction {
if !controller.player.is_playing_animation(anims.run) {
controller.play(
anims.run,
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Forever,
);
}
} else if !controller.is_playing(anims.idle) {
controller.play(
anims.idle,
DEFAULT_TRANSITION_DURATION,
RepeatAnimation::Forever,
);
}
}
}