Update disabled state flags

This commit is contained in:
AdamWhitehurst 2019-12-31 05:19:23 -08:00
parent ba7ca785f6
commit b67a4835f4
12 changed files with 72 additions and 53 deletions

View File

@ -143,27 +143,29 @@ pub struct CharacterState {
pub action_state: ActionState,
/// Used by `move_state` to disable `action_state` `handle()` calls.
pub action_disabled: bool,
/// Resets after every tick. States that use it should set it every tick.
pub action_disabled_this_tick: bool,
/// Used by `action_state` to disable `move_state` `handle()` calls.
pub move_disabled: bool,
/// Resets after every tick. States that use it should set it every tick.
pub move_disabled_this_tick: bool,
}
impl CharacterState {
/// __Compares `move_state`s for shallow equality (does not check internal struct equality)__
/// Compares `move_state`s for shallow equality (does not check internal struct equality)
pub fn is_same_move_state(&self, other: &Self) -> bool {
// Check if state is the same without looking at the inner data
std::mem::discriminant(&self.move_state) == std::mem::discriminant(&other.move_state)
}
/// __Compares `action_state`s for shallow equality (does not check internal struct equality)__
/// Compares `action_state`s for shallow equality (does not check internal struct equality)
pub fn is_same_action_state(&self, other: &Self) -> bool {
// Check if state is the same without looking at the inner data
std::mem::discriminant(&self.action_state) == std::mem::discriminant(&other.action_state)
}
/// __Compares both `move_state`s and `action_state`a for shallow equality
/// (does not check internal struct equality)__
/// Compares both `move_state`s and `action_state`a for shallow equality
/// (does not check internal struct equality)
pub fn is_same_state(&self, other: &Self) -> bool {
self.is_same_move_state(other) && self.is_same_action_state(other)
}
@ -174,8 +176,8 @@ impl Default for CharacterState {
Self {
move_state: MoveState::Fall(FallState),
action_state: ActionState::Idle(IdleState),
action_disabled: false,
move_disabled: false,
action_disabled_this_tick: false,
move_disabled_this_tick: false,
}
}
}

View File

@ -1,7 +1,7 @@
pub mod item;
// Reexports
pub use item::{Debug, Item, ItemKind, ToolData, ToolKind};
pub use item::{Debug, Item, ItemKind, SwordKind, ToolData, ToolKind};
use crate::assets;
use specs::{Component, HashMapStorage, NullStorage};

View File

@ -10,7 +10,7 @@ mod location;
mod phys;
mod player;
pub mod projectile;
mod states;
pub mod states;
mod stats;
mod visual;
@ -30,7 +30,9 @@ pub use controller::{
Mounting,
};
pub use inputs::CanBuild;
pub use inventory::{item, Inventory, InventoryUpdate, Item, ItemKind, ToolData, ToolKind};
pub use inventory::{
item, Inventory, InventoryUpdate, Item, ItemKind, SwordKind, ToolData, ToolKind,
};
pub use last::Last;
pub use location::Waypoint;
pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};

View File

@ -20,7 +20,7 @@ impl StateHandle for BasicBlockState {
};
// TODO: Apply simple move speed debuff instead
update.character.move_disabled = true;
update.character.move_disabled_this_tick = true;
// Update movement
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
@ -32,7 +32,7 @@ impl StateHandle for BasicBlockState {
if !ecs_data.inputs.secondary.is_pressed() {
update.character.action_state = attempt_wield(ecs_data.stats);
update.character.move_disabled = false;
update.character.move_disabled_this_tick = false;
return update;
}

View File

@ -26,7 +26,7 @@ impl StateHandle for ChargeAttackState {
// Prevent move state handling, handled here
// ecs_data.updater.insert(*ecs_data.entity, OverrideMove);
update.character.action_disabled = true;
update.character.action_disabled_this_tick = true;
update.character.move_state = Run(RunState);
// Move player
@ -55,7 +55,7 @@ impl StateHandle for ChargeAttackState {
// Go back to wielding or idling
update.character.action_state = attempt_wield(ecs_data.stats);
update.character.move_disabled = false;
update.character.move_disabled_this_tick= false;
return update;
}
@ -63,7 +63,7 @@ impl StateHandle for ChargeAttackState {
if self.remaining_duration == Duration::default() || update.vel.0.magnitude_squared() < 10.0
{
update.character.action_state = attempt_wield(ecs_data.stats);
update.character.move_disabled = false;
update.character.move_disabled_this_tick= false;
return update;
}

View File

@ -21,7 +21,7 @@ impl StateHandle for ClimbState {
// Disable actions in this state
update.character.action_state = Idle(IdleState);
update.character.action_disabled = true;
update.character.action_disabled_this_tick = true;
// Move player
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
@ -81,13 +81,13 @@ impl StateHandle for ClimbState {
if ecs_data.inputs.jump.is_pressed() {
// They've climbed atop something, give them a boost
update.character.move_state = Jump(JumpState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
} else {
// Just fall off
update.character.move_state = Fall(FallState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
}
@ -96,7 +96,7 @@ impl StateHandle for ClimbState {
// Remove climb state on ground, otherwise character will get stuck
if ecs_data.physics.on_ground {
update.character.move_state = Stand(StandState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
}

View File

@ -18,7 +18,7 @@ impl StateHandle for GlideState {
};
// Prevent action in this state, set here
update.character.action_disabled = true;
update.character.action_disabled_this_tick = true;
// Defaults for this state
update.character.action_state = Idle(IdleState);

View File

@ -56,11 +56,12 @@ use super::{
};
/// #### A trait for implementing state `handle()`ing logic.
/// _Mimics the typical OOP style state machine pattern, but remains performant and consistent
/// with ECS data-behavior-separation constraint since trait fn's are syntactic sugar for
/// static fn's that accept their implementor's object type as its first parameter. This allows
/// for several benefits over implementing each state's behavior within the `CharacterState` update `System`
/// itself:_
/// _Mimics the typical OOP style state machine pattern where states implement their own behavior,
/// exit conditions, and return new states to the state machine upon exit.
/// This is still performant and consistent with ECS data-behavior-separation constraint
/// since trait fn's are syntactic sugar for static fn's that accept their implementor's
/// object type as its first parameter. This allows for several benefits over implementing
/// each state's behavior within the `CharacterState` update `System` itself:_
///
/// 1. Less cognitive overhead: State's handling logic is next to the its data, and component (inside the state's .rs file).
/// 2. Separation of concerns (between states): all logic within a state's `handle()` is relevant only to that state.

View File

@ -20,7 +20,7 @@ impl StateHandle for RollState {
};
// Prevent move state handling, handled here
update.character.move_disabled = true;
update.character.move_disabled_this_tick= true;
// Update velocity
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
@ -39,7 +39,7 @@ impl StateHandle for RollState {
if self.remaining_duration == Duration::default() {
// If so, go back to wielding or idling
update.character.action_state = attempt_wield(ecs_data.stats);
update.character.move_disabled = false;
update.character.move_disabled_this_tick= false;
return update;
}

View File

@ -17,7 +17,7 @@ impl StateHandle for SitState {
};
// Prevent action state handling
update.character.action_disabled = true;
update.character.action_disabled_this_tick = true;
update.character.action_state = Idle(IdleState);
update.character.move_state = Sit(SitState);
@ -27,27 +27,27 @@ impl StateHandle for SitState {
// Can't hurt to be safe :shrug:
if !ecs_data.physics.on_ground {
update.character.move_state = determine_fall_or_swim(ecs_data.physics);
update.character.move_disabled = false;
update.character.move_disabled_this_tick = false;
return update;
}
// Try to jump
if ecs_data.inputs.jump.is_pressed() {
update.character.move_state = Jump(JumpState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
}
// Try to Run
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
update.character.move_state = Run(RunState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
}
// Try to Stand
if ecs_data.inputs.sit.is_just_pressed() {
update.character.move_state = Stand(StandState);
update.character.action_disabled = false;
update.character.action_disabled_this_tick = false;
return update;
}

View File

@ -107,7 +107,10 @@ impl<'a> System<'a> for Sys {
}
// Determine new move state if character can move
if let (None, false) = (move_overrides.get(entity), character.move_disabled) {
if let (None, false) = (
move_overrides.get(entity),
character.move_disabled_this_tick,
) {
let state_update = character.move_state.handle(&EcsStateData {
entity: &entity,
uid,
@ -131,8 +134,15 @@ impl<'a> System<'a> for Sys {
*ori = state_update.ori;
}
// Reset disabled every tick. Should be
// set every tick by states that use it.
character.move_disabled_this_tick = false;
// Determine new action if character can act
if let (None, false) = (action_overrides.get(entity), character.action_disabled) {
if let (None, false) = (
action_overrides.get(entity),
character.action_disabled_this_tick,
) {
let state_update = character.action_state.handle(&EcsStateData {
entity: &entity,
uid,
@ -155,6 +165,10 @@ impl<'a> System<'a> for Sys {
*vel = state_update.vel;
*ori = state_update.ori;
}
// Reset disabled every tick. Should
// be set every tick by states that use it.
character.action_disabled_this_tick = false;
}
}
}

View File

@ -7,7 +7,7 @@ use common::{
comp::{
ActionState, AttackKind::*, BasicAttackState, Body, CharacterState, DodgeKind::*,
FallState, GlideState, IdleState, ItemKind, MoveState, Pos, RollState, RunState,
StandState, Stats, ToolData,
StandState, Stats, SwordKind::*, ToolData, ToolKind::*,
},
event::{EventBus, SfxEvent, SfxEventItem},
};
@ -279,8 +279,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Stand(StandState),
action_state: ActionState::Idle(IdleState),
action_disabled: false,
move_disabled: false,
action_disabled_this_tick: false,
move_disabled_this_tick: false,
},
SfxEvent::Idle,
&stats,
@ -297,8 +297,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Run(RunState),
action_state: ActionState::Idle(IdleState),
action_disabled: false,
move_disabled: false,
action_disabled_this_tick: false,
move_disabled_this_tick: false,
},
SfxEvent::Idle,
&stats,
@ -315,8 +315,8 @@ mod tests {
&CharacterState {
action_state: ActionState::Dodge(Roll(RollState::default())),
move_state: MoveState::Run(RunState),
action_disabled: false,
move_disabled: true,
action_disabled_this_tick: false,
move_disabled_this_tick: true,
},
SfxEvent::Run,
&stats,
@ -333,8 +333,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Fall(FallState),
action_state: ActionState::Idle(IdleState),
action_disabled: false,
move_disabled: false,
action_disabled_this_tick: false,
move_disabled_this_tick: false,
},
SfxEvent::Idle,
&stats,
@ -351,8 +351,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Glide(GlideState),
action_state: ActionState::Idle(IdleState),
action_disabled: true,
move_disabled: false,
action_disabled_this_tick: true,
move_disabled_this_tick: false,
},
SfxEvent::Jump,
&stats,
@ -369,8 +369,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Glide(GlideState),
action_state: ActionState::Idle(IdleState),
action_disabled: true,
move_disabled: false,
action_disabled_this_tick: true,
move_disabled_this_tick: false,
},
SfxEvent::Glide,
&stats,
@ -387,8 +387,8 @@ mod tests {
&CharacterState {
move_state: MoveState::Fall(FallState),
action_state: ActionState::Idle(IdleState),
move_disabled: false,
action_disabled: false,
move_disabled_this_tick: false,
action_disabled_this_tick: false,
},
SfxEvent::Glide,
&stats,
@ -410,13 +410,13 @@ mod tests {
&CharacterState {
move_state: MoveState::Stand(StandState),
action_state: ActionState::Attack(BasicAttack(BasicAttackState::default())),
move_disabled: false,
action_disabled: false,
move_disabled_this_tick: false,
action_disabled_this_tick: false,
},
SfxEvent::Idle,
&stats,
);
assert_eq!(result, SfxEvent::Attack(Tool::Sword));
// assert_eq!(result, SfxEvent::Attack(Sword(_)));
}
}