2019-12-26 14:43:59 +00:00
|
|
|
// Module declarations
|
2020-01-08 16:56:36 +00:00
|
|
|
pub mod basic_attack;
|
|
|
|
pub mod basic_block;
|
|
|
|
pub mod charge_attack;
|
|
|
|
pub mod climb;
|
|
|
|
pub mod fall;
|
|
|
|
pub mod glide;
|
|
|
|
pub mod idle;
|
|
|
|
pub mod jump;
|
|
|
|
pub mod roll;
|
|
|
|
pub mod run;
|
|
|
|
pub mod sit;
|
|
|
|
pub mod stand;
|
|
|
|
pub mod swim;
|
|
|
|
pub mod wield;
|
2019-12-26 14:43:59 +00:00
|
|
|
|
|
|
|
use super::{
|
2019-12-28 16:10:39 +00:00
|
|
|
ActionState, ActionState::*, AttackKind::*, BlockKind::*, DodgeKind::*, EcsStateData,
|
|
|
|
MoveState, MoveState::*, StateUpdate,
|
2019-12-26 14:43:59 +00:00
|
|
|
};
|
2020-01-05 18:19:09 +00:00
|
|
|
|
2020-01-07 15:49:08 +00:00
|
|
|
/// ## A type for implementing State Handling Behavior.
|
|
|
|
///
|
|
|
|
/// Called by state machines' update functions to allow current states to handle updating
|
|
|
|
/// their parent machine's current state.
|
|
|
|
///
|
|
|
|
/// Structures must implement a `handle()` fn to handle update behavior, and a `new()` for
|
|
|
|
/// instantiating new instances of a state. `handle()` function recieves `EcsStateData`, a struct
|
|
|
|
/// of readonly ECS Component data, and returns a `StateUpdate` tuple, with new components that will
|
|
|
|
/// overwrite an entitie's old components.
|
|
|
|
///
|
|
|
|
/// ## Example Implementation:
|
|
|
|
/// ```
|
2020-01-08 13:17:36 +00:00
|
|
|
/// use crate::util::state_utils::*;
|
|
|
|
///
|
2020-01-07 15:49:08 +00:00
|
|
|
/// #[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
/// pub struct RunState {
|
|
|
|
/// active_duration: Duration,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl StateHandler for RunState {
|
|
|
|
/// fn new(ecs_data: &EcsStateData) -> Self {
|
|
|
|
/// Self {
|
|
|
|
/// active_duration: Duration::default(),
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
|
|
|
/// let mut update = StateUpdate {
|
|
|
|
/// character: *ecs_data.character,
|
|
|
|
/// pos: *ecs_data.pos,
|
|
|
|
/// vel: *ecs_data.vel,
|
|
|
|
/// ori: *ecs_data.ori,
|
|
|
|
/// };
|
|
|
|
///
|
2020-01-08 13:17:36 +00:00
|
|
|
/// // Update player's Vel
|
2020-01-07 15:49:08 +00:00
|
|
|
/// update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
|
|
|
/// * ecs_data.inputs.move_dir
|
|
|
|
/// * if update.vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) {
|
|
|
|
/// HUMANOID_ACCEL
|
|
|
|
/// } else {
|
|
|
|
/// 0.0
|
|
|
|
/// };
|
|
|
|
///
|
2020-01-08 13:17:36 +00:00
|
|
|
/// // -- snip --
|
|
|
|
/// // Other updates; checks for gliding, climbing, etc.
|
2020-01-07 15:49:08 +00:00
|
|
|
///
|
|
|
|
/// // Try to jump
|
2020-01-08 13:17:36 +00:00
|
|
|
/// if state_utils::can_jump(ecs_data.physics, ecs_data.inputs) {
|
|
|
|
/// update.character.move_state = Jump(None);
|
2020-01-07 15:49:08 +00:00
|
|
|
/// return update;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // Update based on groundedness
|
|
|
|
/// update.character.move_state =
|
2020-01-08 13:17:36 +00:00
|
|
|
/// state_utils::determine_move_from_grounded_state(ecs_data.physics, ecs_data.inputs);
|
2020-01-07 15:49:08 +00:00
|
|
|
///
|
|
|
|
/// return update;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2020-01-05 18:19:09 +00:00
|
|
|
pub trait StateHandler: Default {
|
2019-12-28 16:10:39 +00:00
|
|
|
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate;
|
2020-01-05 23:17:22 +00:00
|
|
|
fn new(ecs_data: &EcsStateData) -> Self;
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-05 23:17:22 +00:00
|
|
|
// fn's relating to individual `ActionState`s
|
|
|
|
// or passing data from system to handlers
|
2020-01-05 18:19:09 +00:00
|
|
|
impl ActionState {
|
2020-01-05 23:17:22 +00:00
|
|
|
/// Passes data to variant or subvariant handlers
|
|
|
|
/// States contain `Option<StateHandler Implementor>`s, and will be
|
|
|
|
/// `None` if state data has not been initialized. So we have to
|
|
|
|
/// check and intialize new state data if so.
|
2020-01-05 18:19:09 +00:00
|
|
|
pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
2019-12-26 14:43:59 +00:00
|
|
|
match self {
|
|
|
|
Attack(kind) => match kind {
|
2020-01-05 23:17:22 +00:00
|
|
|
BasicAttack(opt_state) => opt_state
|
|
|
|
// If data hasn't been initialized, initialize a new one
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| basic_attack::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
// Call handler
|
|
|
|
.handle(ecs_data),
|
|
|
|
Charge(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| charge_attack::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
2019-12-26 14:43:59 +00:00
|
|
|
},
|
|
|
|
Block(kind) => match kind {
|
2020-01-05 23:17:22 +00:00
|
|
|
BasicBlock(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| basic_block::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
2019-12-26 14:43:59 +00:00
|
|
|
},
|
|
|
|
Dodge(kind) => match kind {
|
2020-01-05 23:17:22 +00:00
|
|
|
Roll(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| roll::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
2019-12-26 14:43:59 +00:00
|
|
|
},
|
2020-01-05 23:17:22 +00:00
|
|
|
Wield(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| wield::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Idle(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| idle::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
2019-12-26 14:43:59 +00:00
|
|
|
// All states should be explicitly handled
|
|
|
|
// Do not use default match: _ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 17:16:29 +00:00
|
|
|
/// Returns whether a given `ActionState` overrides `MoveState` `handle()`ing
|
|
|
|
pub fn overrides_move_state(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Attack(kind) => match kind {
|
2020-01-05 18:19:09 +00:00
|
|
|
BasicAttack(_) => false,
|
|
|
|
Charge(_) => true,
|
2020-01-01 17:16:29 +00:00
|
|
|
},
|
|
|
|
Block(kind) => match kind {
|
2020-01-05 18:19:09 +00:00
|
|
|
BasicBlock(_) => true,
|
2020-01-01 17:16:29 +00:00
|
|
|
},
|
|
|
|
Dodge(kind) => match kind {
|
2020-01-05 18:19:09 +00:00
|
|
|
Roll(_) => true,
|
2020-01-01 17:16:29 +00:00
|
|
|
},
|
2020-01-05 18:19:09 +00:00
|
|
|
Wield(_) => false,
|
|
|
|
Idle(_) => false,
|
2020-01-01 17:16:29 +00:00
|
|
|
// All states should be explicitly handled
|
|
|
|
// Do not use default match: _ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-05 23:17:22 +00:00
|
|
|
// fn's that relate to individual `MoveState`s
|
|
|
|
// or passing data from system to handlers
|
2020-01-01 17:16:29 +00:00
|
|
|
impl MoveState {
|
2020-01-05 23:17:22 +00:00
|
|
|
/// Passes data to variant or subvariant handlers
|
|
|
|
/// States contain `Option<StateHandler Implementor>`s, and will be
|
|
|
|
/// `None` if state data has not been initialized. So we have to
|
|
|
|
/// check and intialize new state data if so.
|
2020-01-01 17:16:29 +00:00
|
|
|
pub fn overrides_action_state(&self) -> bool {
|
|
|
|
match self {
|
2020-01-05 18:19:09 +00:00
|
|
|
Stand(_) => false,
|
|
|
|
Run(_) => false,
|
|
|
|
Jump(_) => false,
|
|
|
|
Climb(_) => true,
|
|
|
|
Glide(_) => true,
|
|
|
|
Swim(_) => false,
|
|
|
|
Fall(_) => false,
|
|
|
|
Sit(_) => true,
|
2020-01-01 17:16:29 +00:00
|
|
|
// All states should be explicitly handled
|
|
|
|
// Do not use default match: _ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
/// Passes handle to variant handlers
|
2020-01-05 18:19:09 +00:00
|
|
|
pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
2019-12-26 14:43:59 +00:00
|
|
|
match self {
|
2020-01-05 23:17:22 +00:00
|
|
|
Stand(opt_state) => opt_state
|
|
|
|
// If data hasn't been initialized, initialize a new one
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| stand::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
// Call handler
|
|
|
|
.handle(ecs_data),
|
|
|
|
Run(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| run::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Jump(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| jump::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Climb(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| climb::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Glide(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| glide::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Swim(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| swim::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Fall(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| fall::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
Sit(opt_state) => opt_state
|
2020-01-08 16:56:36 +00:00
|
|
|
.unwrap_or_else(|| sit::State::new(ecs_data))
|
2020-01-05 23:17:22 +00:00
|
|
|
.handle(ecs_data),
|
2019-12-26 14:43:59 +00:00
|
|
|
// All states should be explicitly handled
|
|
|
|
// Do not use default match: _ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|