Port to fixed point math
This commit is contained in:
@@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher};
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::{FighterStateImpl, FighterStateContext, FighterStateTransition, ground, run, wait, walk};
|
||||
use super::{FighterStateImpl, FighterStateContext, ground, run, wait, walk};
|
||||
use crate::fighter::state::ground::GroundedStateCommon;
|
||||
use crate::fighter::state::wait::WaitState;
|
||||
use crate::fighter::state::{FighterState};
|
||||
@@ -12,11 +12,12 @@ use crate::input::{
|
||||
FighterCommands::{SmashMoveLeft, SmashMoveRight},
|
||||
FighterInput,
|
||||
};
|
||||
use crate::math::int::FGi32;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DashState {
|
||||
frames_in_dash: u32,
|
||||
direction: f32,
|
||||
direction: FGi32,
|
||||
ground_common: GroundedStateCommon
|
||||
}
|
||||
|
||||
@@ -28,7 +29,7 @@ impl std::hash::Hash for DashState {
|
||||
}
|
||||
|
||||
impl DashState {
|
||||
pub fn new(direction: f32, ground_common: GroundedStateCommon) -> Self {
|
||||
pub fn new(direction: FGi32, ground_common: GroundedStateCommon) -> Self {
|
||||
Self {
|
||||
frames_in_dash: 0,
|
||||
direction,
|
||||
@@ -98,11 +99,11 @@ impl FighterStateImpl for DashState {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_smash_input_with_dir(state_context: &FighterStateContext) -> Option<f32> {
|
||||
fn check_smash_input_with_dir(state_context: &FighterStateContext) -> Option<FGi32> {
|
||||
if state_context.input.has_command(SmashMoveLeft) {
|
||||
return Some(-1.0);
|
||||
return Some(FGi32::NEG_ONE);
|
||||
} else if state_context.input.has_command(SmashMoveRight) {
|
||||
return Some(1.0);
|
||||
return Some(FGi32::ONE);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::{FighterStateImpl, FighterStateContext, FighterStateTransition, ground, walk};
|
||||
use super::{FighterStateImpl, FighterStateContext, ground, walk};
|
||||
use crate::fighter::state::{FighterState, air};
|
||||
use crate::fighter::state::ground::GroundedStateCommon;
|
||||
use crate::fighter::state::wait::WaitState;
|
||||
|
||||
+21
-23
@@ -7,17 +7,20 @@ use crate::fighter::{
|
||||
FighterAttributes, FighterECB, FighterPreviousTranslation, FighterTranslation, FighterVelocity,
|
||||
};
|
||||
use crate::game_settings::GameSettings;
|
||||
use crate::math::int::FGi32;
|
||||
use crate::math::vec::FGVec2;
|
||||
use crate::stage::StagePoly;
|
||||
use crate::stage::line::{StageCollision, StageLineID, StagePolyLineSegment, StagePolyLineSegmentType};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use fixed::traits::Fixed;
|
||||
|
||||
#[derive(Reflect, Hash, Clone, Debug)]
|
||||
pub struct GroundedStateCommon {
|
||||
pub current_line_id: StageLineID,
|
||||
}
|
||||
|
||||
pub fn apply_grounded_friction(friction: f32, ground_vel: f32) -> f32 {
|
||||
pub fn apply_grounded_friction(friction: FGi32, ground_vel: FGi32) -> FGi32 {
|
||||
if friction.abs() > ground_vel.abs() {
|
||||
-ground_vel
|
||||
} else {
|
||||
@@ -28,21 +31,21 @@ pub fn apply_grounded_friction(friction: f32, ground_vel: f32) -> f32 {
|
||||
pub fn move_accelerate() {}
|
||||
|
||||
pub fn compute_ground_accel(
|
||||
accel: f32,
|
||||
target_vel: f32,
|
||||
gr_vel: f32,
|
||||
accel: FGi32,
|
||||
target_vel: FGi32,
|
||||
gr_vel: FGi32,
|
||||
attribs: &FighterAttributes,
|
||||
game_settings: &GameSettings,
|
||||
) -> f32 {
|
||||
) -> FGi32 {
|
||||
if target_vel == 0.0 {
|
||||
apply_grounded_friction(attribs.ground_friction, gr_vel)
|
||||
} else {
|
||||
let mut accel = accel;
|
||||
let ground_max_horizontal_velocity =
|
||||
game_settings.figher_common.ground_max_horizontal_velocity;
|
||||
if !(gr_vel * accel < 0.0) {
|
||||
if !(gr_vel * accel < FGi32::ZERO) {
|
||||
// accelerating, not reversing
|
||||
if accel > 0.0 {
|
||||
if accel > FGi32::ZERO {
|
||||
if gr_vel + accel > target_vel {
|
||||
accel = -attribs.ground_friction;
|
||||
if gr_vel + accel < target_vel {
|
||||
@@ -78,7 +81,7 @@ pub fn apply_grounded_motion(
|
||||
) {
|
||||
// Vertical velocity should be 0 on the ground
|
||||
prev_translation.0 = translation.0;
|
||||
translation.0 += Vec2::new(velocity.0.x ,0.0);
|
||||
translation.0 += FGVec2::new(velocity.0.x ,FGi32::ZERO);
|
||||
}
|
||||
|
||||
pub fn collide_with_stage_grounded(
|
||||
@@ -96,34 +99,29 @@ pub fn collide_with_stage_grounded(
|
||||
|
||||
if let Some(stage_poly) = stage_poly {
|
||||
let ecb_bottom_pos = translation.0 + ecb.get_bottom_point();
|
||||
let left_segment_idx = ground_common
|
||||
.current_line_id
|
||||
.segment
|
||||
.checked_sub(1)
|
||||
.unwrap_or(0);
|
||||
let right_segment_idx =
|
||||
(ground_common.current_line_id.segment + 1) % stage_poly.segments.len();
|
||||
let current_segment_idx = ground_common.current_line_id.segment;
|
||||
|
||||
// First, we check the current segment, if that fails, we check the surrounding ones
|
||||
let grounded_ecb_bottom_pos = [
|
||||
ground_common.current_line_id.segment.clone(),
|
||||
left_segment_idx,
|
||||
right_segment_idx,
|
||||
Some(current_segment_idx),
|
||||
stage_poly.get_prev_segment_index(current_segment_idx),
|
||||
stage_poly.get_next_segment_index(current_segment_idx),
|
||||
]
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.find_map(|segment_idx| {
|
||||
let segment = stage_poly.get_segment(*segment_idx)?;
|
||||
let segment = stage_poly.get_segment(segment_idx)?;
|
||||
if segment.segment_type != StagePolyLineSegmentType::Floor {
|
||||
return None;
|
||||
}
|
||||
|
||||
let line_dir = segment.segment.direction();
|
||||
let projected_point = segment.segment.point1() + (ecb_bottom_pos - segment.segment.point1()).project_onto(line_dir.as_vec2());
|
||||
let projected_point = segment.segment.point1() + (ecb_bottom_pos - segment.segment.point1()).project_onto(line_dir);
|
||||
let closest_point = segment.segment.closest_point(ecb_bottom_pos);
|
||||
let distance = closest_point.distance(projected_point);
|
||||
|
||||
|
||||
if distance < 0.01 {
|
||||
return Some((projected_point, *segment_idx, segment.normal));
|
||||
return Some((projected_point, segment_idx, segment.normal));
|
||||
}
|
||||
|
||||
None
|
||||
|
||||
+85
-20
@@ -1,41 +1,106 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::fighter::state::{FighterState, FighterStateImpl};
|
||||
use crate::{
|
||||
fighter::state::{
|
||||
FighterState, FighterStateContext, FighterStateImpl,
|
||||
fall::FallState,
|
||||
ground::{self, GroundedMotionResult, GroundedStateCommon},
|
||||
},
|
||||
input::FighterCommands,
|
||||
};
|
||||
|
||||
pub struct JumpState {
|
||||
pub counter: u32
|
||||
pub enum JumpType {
|
||||
ShortHop,
|
||||
LongJump,
|
||||
DoubleJump,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct JumpState {}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct JumpSquatState {
|
||||
pub counter: u32
|
||||
pub grounded_common: GroundedStateCommon,
|
||||
pub duration_counter: u32,
|
||||
}
|
||||
|
||||
impl JumpSquatState {
|
||||
pub fn create(grounded_common: GroundedStateCommon) -> Self {
|
||||
Self {
|
||||
grounded_common,
|
||||
duration_counter: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FighterStateImpl for JumpSquatState {
|
||||
const NAME: &'static str = "JumpSquat";
|
||||
fn check_interrupt(
|
||||
&self,
|
||||
state_context: &super::FighterStateContext,
|
||||
) -> Option<FighterState> {
|
||||
None
|
||||
|
||||
fn check_interrupt(&self, state_context: &FighterStateContext) -> Option<FighterState> {
|
||||
if self.duration_counter >= state_context.fighter_attribs.jumpsquat_duration {
|
||||
Some(FighterState::Jump(JumpState {}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, _state_context: &mut super::FighterStateContext) {
|
||||
todo!()
|
||||
fn update(&mut self, state_context: &mut FighterStateContext) {
|
||||
self.duration_counter += 1;
|
||||
|
||||
let friction =
|
||||
if state_context.velocity.x.abs() > state_context.fighter_attribs.max_walk_vel {
|
||||
state_context.fighter_attribs.ground_friction
|
||||
* state_context
|
||||
.game_settings
|
||||
.figher_common
|
||||
.ground_friction_over_walk_speed_multiplier
|
||||
} else {
|
||||
state_context.fighter_attribs.ground_friction
|
||||
};
|
||||
|
||||
let ground_velocity = state_context.velocity.x;
|
||||
|
||||
state_context.velocity.x += ground::apply_grounded_friction(friction, ground_velocity);
|
||||
|
||||
ground::apply_grounded_motion(
|
||||
state_context.velocity,
|
||||
state_context.translation,
|
||||
state_context.prev_translation,
|
||||
);
|
||||
}
|
||||
|
||||
fn check_collision_interrupt(
|
||||
&mut self,
|
||||
state_context: &mut FighterStateContext,
|
||||
) -> Option<FighterState> {
|
||||
if let GroundedMotionResult::InAir =
|
||||
ground::collide_with_stage_grounded(state_context, &mut self.grounded_common, false)
|
||||
{
|
||||
Some(FighterState::Fall(FallState))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl FighterStateImpl for JumpState {
|
||||
const NAME: &'static str = "Jump";
|
||||
fn check_interrupt(
|
||||
&self,
|
||||
state_context: &super::FighterStateContext,
|
||||
) -> Option<FighterState> {
|
||||
fn check_interrupt(&self, state_context: &FighterStateContext) -> Option<FighterState> {
|
||||
None
|
||||
}
|
||||
|
||||
fn update(&mut self, _state_context: &mut super::FighterStateContext) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
fn update(&mut self, _state_context: &mut FighterStateContext) {}
|
||||
}
|
||||
|
||||
pub fn check_input(
|
||||
state_context: &FighterStateContext,
|
||||
ground_common: &GroundedStateCommon,
|
||||
) -> Option<FighterState> {
|
||||
state_context
|
||||
.input
|
||||
.has_command(FighterCommands::Jump)
|
||||
.then_some(FighterState::JumpSquat(JumpSquatState::create(
|
||||
ground_common.clone(),
|
||||
)));
|
||||
None
|
||||
}
|
||||
|
||||
+13
-13
@@ -11,6 +11,7 @@ use crate::fighter::ecb::FighterPreviousECB;
|
||||
use crate::fighter::{FighterAttributes, FighterECB, FighterPreviousTranslation, FighterTranslation, FighterVelocity};
|
||||
use crate::game_settings::GameSettings;
|
||||
use crate::input::FighterInput;
|
||||
use crate::math::int::FGi32;
|
||||
use crate::schedule::GameplaySet;
|
||||
use crate::stage::StagePoly;
|
||||
use crate::stage::line::StageCollision;
|
||||
@@ -24,14 +25,6 @@ pub mod fall;
|
||||
pub mod air;
|
||||
pub mod jump;
|
||||
|
||||
pub enum FighterStateTransition {
|
||||
Wait,
|
||||
Walk,
|
||||
Dash(f32),
|
||||
Run,
|
||||
Fall,
|
||||
}
|
||||
|
||||
macro_rules! fighter_states {
|
||||
($($variant:ident => $ty:ty),* $(,)?) => {
|
||||
#[derive(Component, Clone, Debug, Hash)]
|
||||
@@ -80,7 +73,7 @@ pub trait FighterStateImpl: Sized {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FighterStateContext<'a> {
|
||||
pub struct FighterStateContext<'a, 'w, 's> {
|
||||
pub translation: &'a mut FighterTranslation,
|
||||
pub prev_translation: &'a mut FighterPreviousTranslation,
|
||||
pub input: &'a mut FighterInput,
|
||||
@@ -91,6 +84,7 @@ pub struct FighterStateContext<'a> {
|
||||
pub game_settings: &'a GameSettings,
|
||||
pub entity: Entity,
|
||||
pub stage_collision: &'a StageCollision,
|
||||
pub gizmos: Option<&'a mut Gizmos<'w, 's>>,
|
||||
}
|
||||
|
||||
fighter_states! {
|
||||
@@ -98,7 +92,9 @@ fighter_states! {
|
||||
Walk => walk::WalkState,
|
||||
Dash => dash::DashState,
|
||||
Run => run::RunState,
|
||||
Fall => fall::FallState
|
||||
Fall => fall::FallState,
|
||||
JumpSquat => jump::JumpSquatState,
|
||||
Jump => jump::JumpState
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
@@ -128,6 +124,7 @@ pub fn state_update_system(
|
||||
game_settings: &game_settings,
|
||||
entity: ent,
|
||||
stage_collision: &stage_collision,
|
||||
gizmos: Some(&mut gizmos),
|
||||
};
|
||||
state.update(&mut update_ctx);
|
||||
}
|
||||
@@ -150,7 +147,8 @@ pub fn state_interrupt_system (
|
||||
fighter_attribs: &attribs,
|
||||
game_settings: &game_settings,
|
||||
entity: ent,
|
||||
stage_collision: &stage_collision
|
||||
stage_collision: &stage_collision,
|
||||
gizmos: None,
|
||||
};
|
||||
if let Some(new_state) = state.check_interrupt(&state_context) {
|
||||
let mut new_state = new_state;
|
||||
@@ -171,6 +169,7 @@ pub fn state_collision_interrupt_system(
|
||||
stage_collision: Res<StageCollision>,
|
||||
game_settings: Res<GameSettings>,
|
||||
mut commands: Commands,
|
||||
mut gizmos: Gizmos,
|
||||
) {
|
||||
for (ent, mut state, mut translation, mut prev_translation, mut input, mut velocity, mut ecb, mut prev_ecb, attribs) in query {
|
||||
let mut state_context = FighterStateContext {
|
||||
@@ -183,7 +182,8 @@ pub fn state_collision_interrupt_system(
|
||||
fighter_attribs: &attribs,
|
||||
game_settings: &game_settings,
|
||||
entity: ent,
|
||||
stage_collision: &stage_collision
|
||||
stage_collision: &stage_collision,
|
||||
gizmos: Some(&mut gizmos),
|
||||
};
|
||||
if let Some(new_state) = state.check_collision_interrupt(&mut state_context) {
|
||||
let mut new_state = new_state;
|
||||
@@ -197,4 +197,4 @@ pub fn state_collision_interrupt_system(
|
||||
info!("State {} -> {}", old_state_name, new_state_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::{FighterStateImpl, FighterStateContext, FighterStateTransition, ground, wait, walk};
|
||||
use super::{FighterStateImpl, FighterStateContext, ground, wait, walk};
|
||||
use crate::fighter::state::FighterState;
|
||||
use crate::fighter::state::fall::FallState;
|
||||
use crate::fighter::state::ground::{GroundedMotionResult, GroundedStateCommon};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::{FighterStateImpl, FighterStateContext, FighterStateTransition, ground, walk};
|
||||
use super::{FighterStateImpl, FighterStateContext, ground, walk};
|
||||
use crate::fighter::state::FighterState;
|
||||
use crate::fighter::state::fall::FallState;
|
||||
use crate::fighter::state::ground::{GroundedMotionResult, GroundedStateCommon};
|
||||
@@ -33,7 +33,10 @@ impl FighterStateImpl for WaitState {
|
||||
} else {
|
||||
state_context.fighter_attribs.ground_friction
|
||||
};
|
||||
state_context.velocity.x += ground::apply_grounded_friction(friction, state_context.velocity.x);
|
||||
|
||||
let ground_velocity = state_context.velocity.x;
|
||||
|
||||
state_context.velocity.x += ground::apply_grounded_friction(friction, ground_velocity);
|
||||
|
||||
ground::apply_grounded_motion(
|
||||
state_context.velocity,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::{FighterStateImpl, FighterStateContext, FighterStateTransition, dash, ground, wait};
|
||||
use super::{FighterStateImpl, FighterStateContext, dash, ground, wait};
|
||||
use crate::fighter::state::fall::FallState;
|
||||
use crate::fighter::state::ground::{GroundedMotionResult, GroundedStateCommon};
|
||||
use crate::fighter::state::{self, FighterState};
|
||||
|
||||
Reference in New Issue
Block a user