Files
shinespark/src/fighter/visual.rs
T
EIREXE 895a8b8756
CI / build-and-test (pull_request) Successful in 2m8s
CI / production-build (pull_request) Successful in 11m7s
Implement invulnerability/intangibility and sakurai angle
2026-09-29 19:36:48 +02:00

92 lines
3.3 KiB
Rust

use crate::{
fighter::{FighterInvulnerabilityState, baked_animation::BakedFighterAnimations},
game_settings::GameSettings,
materials::fighter_material::{FighterMaterial, FighterMesh},
};
use bevy::prelude::*;
#[derive(Component, Clone)]
pub struct FighterAnimations {
/// The single animation source for gameplay and the visual skeleton.
pub baked: Handle<BakedFighterAnimations>,
}
#[derive(Clone, Copy, Default, PartialEq)]
pub enum LastKnownInvulnerabilityState {
#[default]
Vulnerable,
Intangible,
Invulnerable,
}
impl From<&FighterInvulnerabilityState> for LastKnownInvulnerabilityState {
fn from(value: &FighterInvulnerabilityState) -> Self {
match value {
FighterInvulnerabilityState::Vulnerable => Self::Vulnerable,
FighterInvulnerabilityState::Invulnerable { .. } => Self::Invulnerable,
FighterInvulnerabilityState::Intangible { .. } => Self::Intangible,
}
}
}
#[derive(Component, Clone, Default)]
pub struct FighterInvulnerabilityVisualState {
pub last_known_state: LastKnownInvulnerabilityState,
pub frames_in_state: u32,
}
pub fn update_status_colors(
mut fighters: Query<(
&FighterInvulnerabilityState,
&mut FighterInvulnerabilityVisualState,
)>,
meshes: Query<(&FighterMesh, &MeshMaterial3d<FighterMaterial>)>,
mut materials: ResMut<Assets<FighterMaterial>>,
game_settings: Res<GameSettings>,
) {
for (invuln_state, mut invuln_state_visual) in &mut fighters {
let curr_state = invuln_state.into();
let last_known_state = invuln_state_visual.last_known_state;
if curr_state != last_known_state {
invuln_state_visual.last_known_state = curr_state;
invuln_state_visual.frames_in_state = 0;
}
}
for (mesh, mat) in meshes {
let (_, invuln_state_visual) = fighters
.get(mesh.fighter)
.expect("Material should have relevant fighter available");
let status_color = match invuln_state_visual.last_known_state {
LastKnownInvulnerabilityState::Vulnerable => bevy::color::palettes::css::WHITE.into(),
LastKnownInvulnerabilityState::Invulnerable => {
game_settings.fighter_common.intangible_color
}
LastKnownInvulnerabilityState::Intangible => {
game_settings.fighter_common.intangible_color
}
};
let intensity = match invuln_state_visual.last_known_state {
LastKnownInvulnerabilityState::Vulnerable => 0.0,
LastKnownInvulnerabilityState::Invulnerable | LastKnownInvulnerabilityState::Intangible => {
let cycle_frames = invuln_state_visual.frames_in_state
% game_settings.fighter_common.intangible_pulse_duration;
1.0 - cycle_frames as f32
/ ((game_settings.fighter_common.intangible_pulse_duration) as f32)
}
};
let mut material = materials
.get_mut(mat.id())
.expect("Material should exist here...");
material
.extension
.update_status_color(status_color.into(), intensity);
}
for (_, mut invuln_state_visual) in fighters {
invuln_state_visual.frames_in_state = invuln_state_visual.frames_in_state.saturating_add(1);
}
}