Implement hitstun and knockback.
This commit is contained in:
+75
-11
@@ -8,20 +8,26 @@ use bevy_egui::{EguiContexts, egui};
|
||||
|
||||
use crate::debug_tools::{DebugSettings, FighterDebugRowKind};
|
||||
use crate::fighter::animation::FighterAnimationFrame;
|
||||
use crate::fighter::attack::FighterSolvedHurtboxes;
|
||||
use crate::fighter::attack::{
|
||||
FighterKnockbackVelocity, FighterLastAttackDebug, FighterPendingHitReaction,
|
||||
FighterSolvedHurtboxes,
|
||||
};
|
||||
use crate::fighter::baked_animation::{BakedFighterAnimations, FighterBoneMatrices};
|
||||
use crate::fighter::ecb::FighterPreviousECB;
|
||||
use crate::fighter::errors::FighterErrors;
|
||||
use crate::fighter::hurtbox::FixedAffineCapsule;
|
||||
use crate::fighter::state::StateNameDebug;
|
||||
use crate::fighter::manifest::FighterManifest;
|
||||
use crate::fighter::state::{FighterState, air};
|
||||
use crate::fighter::visual::FighterAnimations;
|
||||
use crate::fighter::{
|
||||
FighterECB, FighterFacingDirection, FighterHitboxes, FighterPreviousTranslation,
|
||||
Fighter, FighterECB, FighterFacingDirection, FighterHitboxes, FighterPreviousTranslation,
|
||||
FighterTranslation, FighterVelocity,
|
||||
};
|
||||
use crate::game_settings::GameSettings;
|
||||
use crate::input::FighterInput;
|
||||
use crate::math::int::FGi32;
|
||||
use crate::math::vec::FGVec2;
|
||||
use crate::player::Player;
|
||||
use crate::scripting::FighterAttackScript;
|
||||
|
||||
pub fn debug_draw_ecb(
|
||||
ecbs: Query<(
|
||||
@@ -51,7 +57,7 @@ pub fn fighter_debug(
|
||||
&FighterVelocity,
|
||||
&FighterInput,
|
||||
&FighterAnimationFrame,
|
||||
&StateNameDebug,
|
||||
&FighterState,
|
||||
&FighterAnimations,
|
||||
&FighterTranslation,
|
||||
&FighterFacingDirection,
|
||||
@@ -62,7 +68,7 @@ pub fn fighter_debug(
|
||||
let mut fighters = query.iter().collect::<Vec<_>>();
|
||||
fighters.sort_unstable_by_key(|(player, ..)| player.handle);
|
||||
|
||||
for (player, velocity, input, animation_frame, state_name, animations, translation, facing) in
|
||||
for (player, velocity, input, animation_frame, state, animations, translation, facing) in
|
||||
fighters
|
||||
{
|
||||
let Some(rows) = settings.player_rows(player.handle) else {
|
||||
@@ -85,7 +91,7 @@ pub fn fighter_debug(
|
||||
if let Some(frame_count) = frame_count {
|
||||
ui.label(format!(
|
||||
"State: {:?} ({:?} {}/{})",
|
||||
state_name.0,
|
||||
state.name(),
|
||||
animation_frame.kind,
|
||||
animation_frame.frame,
|
||||
frame_count
|
||||
@@ -93,7 +99,8 @@ pub fn fighter_debug(
|
||||
} else {
|
||||
ui.label(format!(
|
||||
"State: {:?} ({:?})",
|
||||
state_name.0, animation_frame.kind
|
||||
state.name(),
|
||||
animation_frame.kind
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -334,12 +341,11 @@ pub fn attack_debug(
|
||||
&FighterFacingDirection,
|
||||
&FighterAnimationFrame,
|
||||
)>,
|
||||
_attack_scripts: Res<Assets<FighterAttackScript>>,
|
||||
mut gizmos: Gizmos,
|
||||
) {
|
||||
for (hitboxes, _matrices, _translation, _facing_direction, _frame) in query {
|
||||
if let Some(_script) = &hitboxes.attack_script {
|
||||
for solved_hitbox in hitboxes.active_hitboxes_solved.iter() {
|
||||
if let Some(active_attack) = &hitboxes.0 {
|
||||
for solved_hitbox in active_attack.solved_hitboxes.iter() {
|
||||
let start = solved_hitbox.capsule.start.to_vec3();
|
||||
let end = solved_hitbox.capsule.end.to_vec3();
|
||||
let center =
|
||||
@@ -369,3 +375,61 @@ pub fn attack_debug(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attack_debug_gather(
|
||||
query: Query<(
|
||||
Entity,
|
||||
&FighterPendingHitReaction,
|
||||
&FighterTranslation,
|
||||
&Fighter,
|
||||
)>,
|
||||
mut commands: Commands,
|
||||
manifests: Res<Assets<FighterManifest>>,
|
||||
game_settings: Res<GameSettings>,
|
||||
) -> Result {
|
||||
for (entity, reaction, translation, fighter) in query {
|
||||
let Some(ref hit) = reaction.0 else {
|
||||
commands.entity(entity).remove::<FighterLastAttackDebug>();
|
||||
continue;
|
||||
};
|
||||
|
||||
let manifest = manifests
|
||||
.get(&fighter.manifest)
|
||||
.ok_or(FighterErrors::FighterManifestNotFound)?;
|
||||
|
||||
let mut knockback_vel = FighterKnockbackVelocity(hit.launch_velocity);
|
||||
let mut fighter_vel = FighterVelocity(FGVec2::ZERO);
|
||||
let mut translation = Vec3::new(translation.x.to_num(), translation.y.to_num(), 0.0);
|
||||
|
||||
let mut points = vec![];
|
||||
points.push(translation);
|
||||
points.reserve(hit.hitstun_frames as usize);
|
||||
|
||||
for _ in 1..hit.hitstun_frames {
|
||||
air::integrate_gravity(&mut fighter_vel, &manifest.attributes);
|
||||
|
||||
let vel = knockback_vel.length();
|
||||
let new_vel = vel
|
||||
.saturating_sub(game_settings.fighter_common.knockback_decay_per_frame)
|
||||
.max(FGi32::ZERO);
|
||||
knockback_vel = FighterKnockbackVelocity(knockback_vel.0.normalize_or_zero() * new_vel);
|
||||
translation += Vec3::new(knockback_vel.x.to_num(), knockback_vel.y.to_num(), 0.0);
|
||||
translation += Vec3::new(fighter_vel.x.to_num(), fighter_vel.y.to_num(), 0.0);
|
||||
points.push(translation);
|
||||
}
|
||||
commands.entity(entity).insert(FighterLastAttackDebug {
|
||||
trajectory_points: points,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn attack_launch_debug_draw(query: Query<&FighterLastAttackDebug>, mut gizmos: Gizmos) {
|
||||
for debug_attack in query {
|
||||
gizmos.linestrip(
|
||||
debug_attack.trajectory_points.iter().copied(),
|
||||
bevy::color::palettes::css::GREEN,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user