Rudimentary Stand State handle() move

This commit is contained in:
AdamWhitehurst 2019-12-21 07:57:15 -08:00
parent e40eb2ba20
commit 1ab09220b0
6 changed files with 253 additions and 203 deletions

View File

@ -1,173 +1,16 @@
use crate::comp::{ use crate::comp::{Body, Controller, ControllerInputs, ItemKind, PhysicsState, Stats};
Body, CharacterState, Controller, ControllerInputs, ItemKind, PhysicsState, Stats,
};
use specs::{Component, FlaggedStorage, HashMapStorage}; use specs::{Component, FlaggedStorage, HashMapStorage};
use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System}; use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System};
use sphynx::{Uid, UidAllocator}; use sphynx::{Uid, UidAllocator};
//use specs_idvs::IDVStorage; //use specs_idvs::IDVStorage;
use self::{ActionState::*, MovementState::*}; use self::{ActionState::*, MovementState::*};
use std::time::Duration; use std::time::Duration;
pub trait State {
fn handle(
&self,
character: &CharacterState,
inputs: &ControllerInputs,
stats: &Stats,
body: &Body,
physics: &PhysicsState,
) -> CharacterState;
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct RunData; pub struct RunData;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct StandData; pub struct StandData;
impl State for StandData {
fn handle(
&self,
character: &CharacterState,
inputs: &ControllerInputs,
stats: &Stats,
body: &Body,
physics: &PhysicsState,
) -> CharacterState {
let mut new_move: MovementState = if inputs.move_dir.magnitude_squared() > 0.0 {
MovementState::Run(RunData)
} else {
MovementState::Stand(StandData)
};
// Try to sit
if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() {
return CharacterState {
movement: Sit,
action: Idle,
};
}
// Try to climb
if let (true, Some(_wall_dir)) = (
inputs.climb.is_pressed() | inputs.climb_down.is_pressed() && body.is_humanoid(),
physics.on_wall,
) {
return CharacterState {
movement: Climb,
action: Idle,
};
}
// Try to swim
if !physics.on_ground && physics.in_fluid {
return CharacterState {
action: character.action,
movement: Swim,
};
}
// While on ground ...
if physics.on_ground {
// Try to jump
if inputs.jump.is_pressed() && !inputs.jump.is_held_down() {
return CharacterState {
action: character.action,
movement: Jump,
};
}
// Try to charge
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
return CharacterState {
action: Charge {
time_left: Duration::from_millis(250),
},
movement: Run(RunData),
};
}
// Try to roll
if inputs.roll.is_pressed() && body.is_humanoid() {
return CharacterState {
action: Roll {
time_left: Duration::from_millis(600),
was_wielding: character.action.is_wield(),
},
movement: Run(RunData),
};
}
}
// While not on ground ...
else {
// Try to glide
if physics.on_wall == None
&& inputs.glide.is_pressed()
&& !inputs.glide.is_held_down()
&& body.is_humanoid()
{
return CharacterState {
action: Idle,
movement: Glide,
};
}
return CharacterState {
action: character.action,
movement: Fall,
};
}
// Tool Actions
if inputs.toggle_wield.is_just_pressed() {
match character.action {
Wield { .. } | Attack { .. } => {
// Prevent instantaneous reequipping by checking
// for done wielding
if character.action.is_action_finished() {
return CharacterState {
action: Idle,
movement: character.movement,
};
}
}
Idle => {
return CharacterState {
// Try to wield if an item is equipped in main hand
action: if let Some(ItemKind::Tool { kind, .. }) =
stats.equipment.main.as_ref().map(|i| &i.kind)
{
let wield_duration = kind.wield_duration();
Wield {
time_left: wield_duration,
}
} else {
Idle
},
movement: character.movement,
};
}
Charge { .. } | Roll { .. } | Block { .. } => {}
}
}
if inputs.primary.is_pressed() {
// TODO: PrimaryStart
} else if inputs.secondary.is_pressed() {
// TODO: SecondaryStart
}
if inputs.move_dir.magnitude_squared() > 0.0 {
return CharacterState {
action: character.action,
movement: Run(RunData),
};
} else {
return CharacterState {
action: character.action,
movement: Stand(StandData),
};
}
return character;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub enum MovementState { pub enum MovementState {
Stand(StandData), Stand(StandData),

View File

@ -20,7 +20,7 @@ pub use body::{
biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, humanoid, object, biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, humanoid, object,
quadruped_medium, quadruped_small, Body, quadruped_medium, quadruped_small, Body,
}; };
pub use character_state::{ActionState, CharacterState, MovementState}; pub use character_state::{ActionState, CharacterState, MovementState, RunData, StandData};
pub use controller::{ pub use controller::{
ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState, ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState,
Mounting, Mounting,

View File

@ -1,14 +1,12 @@
use super::movement::ROLL_DURATION; use super::movement::ROLL_DURATION;
const HUMANOID_ACCEL: f32 = 50.0;
const HUMANOID_SPEED: f32 = 120.0;
use crate::{ use crate::{
comp::{ comp::{
self, item, projectile, ActionState, self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
ActionState::*, Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
Body, CharacterState, MovementState, MovementState::*, Ori, PhysicsState, Pos, Projectile, RunData, StandData,
CharacterState::{RunData, StandData}, Stats, Vel,
ControlEvent, Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
MovementState,
MovementState::*,
PhysicsState, Projectile, Stats, Vel,
}, },
event::{Emitter, EventBus, LocalEvent, ServerEvent}, event::{Emitter, EventBus, LocalEvent, ServerEvent},
state::DeltaTime, state::DeltaTime,
@ -33,10 +31,12 @@ impl<'a> System<'a> for Sys {
Read<'a, EventBus<LocalEvent>>, Read<'a, EventBus<LocalEvent>>,
Read<'a, DeltaTime>, Read<'a, DeltaTime>,
WriteStorage<'a, CharacterState>, WriteStorage<'a, CharacterState>,
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
ReadStorage<'a, Controller>, ReadStorage<'a, Controller>,
ReadStorage<'a, Stats>, ReadStorage<'a, Stats>,
ReadStorage<'a, Body>, ReadStorage<'a, Body>,
ReadStorage<'a, Vel>,
ReadStorage<'a, PhysicsState>, ReadStorage<'a, PhysicsState>,
ReadStorage<'a, Uid>, ReadStorage<'a, Uid>,
ReadStorage<'a, Mounting>, ReadStorage<'a, Mounting>,
@ -50,10 +50,12 @@ impl<'a> System<'a> for Sys {
local_bus, local_bus,
dt, dt,
mut character_states, mut character_states,
mut positions,
mut velocities,
mut orientations,
controllers, controllers,
stats, stats,
bodies, bodies,
velocities,
physics_states, physics_states,
uids, uids,
mountings, mountings,
@ -61,14 +63,28 @@ impl<'a> System<'a> for Sys {
) { ) {
let mut server_emitter = server_bus.emitter(); let mut server_emitter = server_bus.emitter();
let mut local_emitter = local_bus.emitter(); let mut local_emitter = local_bus.emitter();
for (entity, uid, mut character, controller, stats, body, vel, physics, mount) in ( for (
entity,
uid,
mut character,
mut pos,
mut vel,
mut ori,
controller,
stats,
body,
physics,
mount,
) in (
&entities, &entities,
&uids, &uids,
&mut character_states, &mut character_states,
&mut positions,
&mut velocities,
&mut orientations,
&controllers, &controllers,
&stats, &stats,
&bodies, &bodies,
&velocities,
&physics_states, &physics_states,
mountings.maybe(), mountings.maybe(),
) )
@ -382,7 +398,7 @@ impl<'a> System<'a> for Sys {
} }
if physics.on_ground { if physics.on_ground {
character.movement = Stand(Stand) character.movement = Stand(StandData)
} }
} }
// Any Action + Climbing, shouldnt care about action, // Any Action + Climbing, shouldnt care about action,
@ -397,9 +413,197 @@ impl<'a> System<'a> for Sys {
} }
} }
if physics.on_ground { if physics.on_ground {
character.movement = Stand(Stand); character.movement = Stand(StandData);
} }
} }
(_, Stand(data)) => {
let mut new_char =
data.handle(character, pos, vel, ori, &dt, inputs, stats, body, physics);
println!("{:?}", new_char);
character = &mut new_char;
}
(_, _) => {
character.movement = Stand(StandData);
}
};
}
}
}
pub trait State {
fn handle(
&self,
character: &CharacterState,
pos: &mut Pos,
vel: &mut Vel,
ori: &mut Ori,
dt: &DeltaTime,
inputs: &ControllerInputs,
stats: &Stats,
body: &Body,
physics: &PhysicsState,
) -> CharacterState;
}
impl State for StandData {
fn handle(
&self,
character: &CharacterState,
pos: &mut Pos,
vel: &mut Vel,
ori: &mut Ori,
dt: &DeltaTime,
inputs: &ControllerInputs,
stats: &Stats,
body: &Body,
physics: &PhysicsState,
) -> CharacterState {
// Move player according to move_dir
vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir
* if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) {
HUMANOID_ACCEL
} else {
0.0
};
// Set direction based on move direction when on the ground
let ori_dir = if character.action.is_attack() || character.action.is_block() {
Vec2::from(inputs.look_dir).normalized()
} else {
Vec2::from(vel.0)
};
if ori_dir.magnitude_squared() > 0.0001
&& (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001
{
ori.0 = vek::ops::Slerp::slerp(ori.0, ori_dir.into(), 9.0 * dt.0);
}
// Try to sit
if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() {
return CharacterState {
movement: Sit,
action: Idle,
};
}
// Try to climb
if let (true, Some(_wall_dir)) = (
inputs.climb.is_pressed() | inputs.climb_down.is_pressed() && body.is_humanoid(),
physics.on_wall,
) {
return CharacterState {
movement: Climb,
action: Idle,
};
}
// Try to swim
if !physics.on_ground && physics.in_fluid {
return CharacterState {
action: character.action,
movement: Swim,
};
}
// While on ground ...
if physics.on_ground {
// Try to jump
if inputs.jump.is_pressed() && !inputs.jump.is_held_down() {
return CharacterState {
action: character.action,
movement: Jump,
};
}
// Try to charge
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
return CharacterState {
action: Charge {
time_left: Duration::from_millis(250),
},
movement: Run(RunData),
};
}
// Try to roll
if inputs.roll.is_pressed() && body.is_humanoid() {
return CharacterState {
action: Roll {
time_left: Duration::from_millis(600),
was_wielding: character.action.is_wield(),
},
movement: Run(RunData),
};
}
}
// While not on ground ...
else {
// Try to glide
if physics.on_wall == None
&& inputs.glide.is_pressed()
&& !inputs.glide.is_held_down()
&& body.is_humanoid()
{
return CharacterState {
action: Idle,
movement: Glide,
};
}
return CharacterState {
action: character.action,
movement: Fall,
};
}
// Tool Actions
if inputs.toggle_wield.is_just_pressed() {
match character.action {
Wield { .. } | Attack { .. } => {
// Prevent instantaneous reequipping by checking
// for done wielding
if character.action.is_action_finished() {
return CharacterState {
action: Idle,
movement: character.movement,
};
}
}
Idle => {
return CharacterState {
// Try to wield if an item is equipped in main hand
action: if let Some(ItemKind::Tool { kind, .. }) =
stats.equipment.main.as_ref().map(|i| &i.kind)
{
let wield_duration = kind.wield_duration();
Wield {
time_left: wield_duration,
}
} else {
Idle
},
movement: character.movement,
};
}
Charge { .. } | Roll { .. } | Block { .. } => {}
}
}
if inputs.primary.is_pressed() {
// TODO: PrimaryStart
} else if inputs.secondary.is_pressed() {
// TODO: SecondaryStart
}
if inputs.move_dir.magnitude_squared() > 0.0 {
return CharacterState {
action: character.action,
movement: Run(RunData),
};
} else {
return CharacterState {
action: character.action,
movement: Stand(StandData),
}; };
} }
} }

View File

@ -1,7 +1,8 @@
use super::phys::GRAVITY; use super::phys::GRAVITY;
use crate::{ use crate::{
comp::{ comp::{
CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, Stats, Vel, CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, RunData,
StandData, Stats, Vel,
}, },
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
state::DeltaTime, state::DeltaTime,
@ -105,7 +106,7 @@ impl<'a> System<'a> for Sys {
) )
.join() .join()
{ {
if character.movement == Run || character.movement == Stand { if character.movement == Run(RunData) || character.movement == Stand(StandData) {
continue; continue;
} }
@ -145,7 +146,7 @@ impl<'a> System<'a> for Sys {
vel.0 += Vec2::broadcast(dt.0) vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir * inputs.move_dir
* match (physics.on_ground, &character.movement) { * match (physics.on_ground, &character.movement) {
(true, Run) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { (true, Run(_)) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => {
HUMANOID_ACCEL HUMANOID_ACCEL
} }
(false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { (false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => {

View File

@ -162,7 +162,7 @@ impl SfxEventMapper {
(_, ActionState::Roll { .. }, ..) => SfxEvent::Roll, (_, ActionState::Roll { .. }, ..) => SfxEvent::Roll,
(MovementState::Climb, ..) => SfxEvent::Climb, (MovementState::Climb, ..) => SfxEvent::Climb,
(MovementState::Swim, ..) => SfxEvent::Swim, (MovementState::Swim, ..) => SfxEvent::Swim,
(MovementState::Run, ..) => SfxEvent::Run, (MovementState::Run(_), ..) => SfxEvent::Run,
(MovementState::Fall, _, previous_event, _) => { (MovementState::Fall, _, previous_event, _) => {
if previous_event != SfxEvent::Glide { if previous_event != SfxEvent::Glide {
SfxEvent::Fall SfxEvent::Fall

View File

@ -197,14 +197,14 @@ impl FigureMgr {
} }
let target_base = match &character.movement { let target_base = match &character.movement {
Stand => anim::character::StandAnimation::update_skeleton( Stand(_) => anim::character::StandAnimation::update_skeleton(
&CharacterSkeleton::new(), &CharacterSkeleton::new(),
(active_tool_kind, time), (active_tool_kind, time),
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::character::RunAnimation::update_skeleton( Run(_) => anim::character::RunAnimation::update_skeleton(
&CharacterSkeleton::new(), &CharacterSkeleton::new(),
(active_tool_kind, vel.0, ori.0, state.last_ori, time), (active_tool_kind, vel.0, ori.0, state.last_ori, time),
state.movement_time, state.movement_time,
@ -248,14 +248,16 @@ impl FigureMgr {
), ),
}; };
let target_bones = match (&character.movement, &character.action) { let target_bones = match (&character.movement, &character.action) {
(Stand, Wield { .. }) => anim::character::CidleAnimation::update_skeleton( (Stand(_), Wield { .. }) => {
&target_base, anim::character::CidleAnimation::update_skeleton(
(active_tool_kind, time), &target_base,
state.action_time, (active_tool_kind, time),
&mut action_animation_rate, state.action_time,
skeleton_attr, &mut action_animation_rate,
), skeleton_attr,
(Stand, Block { .. }) => { )
}
(Stand(_), Block { .. }) => {
anim::character::BlockIdleAnimation::update_skeleton( anim::character::BlockIdleAnimation::update_skeleton(
&target_base, &target_base,
(active_tool_kind, time), (active_tool_kind, time),
@ -333,14 +335,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::quadruped_small::IdleAnimation::update_skeleton( Stand(_) => anim::quadruped_small::IdleAnimation::update_skeleton(
&QuadrupedSmallSkeleton::new(), &QuadrupedSmallSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::quadruped_small::RunAnimation::update_skeleton( Run(_) => anim::quadruped_small::RunAnimation::update_skeleton(
&QuadrupedSmallSkeleton::new(), &QuadrupedSmallSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -390,14 +392,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::quadruped_medium::IdleAnimation::update_skeleton( Stand(_) => anim::quadruped_medium::IdleAnimation::update_skeleton(
&QuadrupedMediumSkeleton::new(), &QuadrupedMediumSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::quadruped_medium::RunAnimation::update_skeleton( Run(_) => anim::quadruped_medium::RunAnimation::update_skeleton(
&QuadrupedMediumSkeleton::new(), &QuadrupedMediumSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -445,14 +447,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::bird_medium::IdleAnimation::update_skeleton( Stand(_) => anim::bird_medium::IdleAnimation::update_skeleton(
&BirdMediumSkeleton::new(), &BirdMediumSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::bird_medium::RunAnimation::update_skeleton( Run(_) => anim::bird_medium::RunAnimation::update_skeleton(
&BirdMediumSkeleton::new(), &BirdMediumSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -500,14 +502,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::fish_medium::IdleAnimation::update_skeleton( Stand(_) => anim::fish_medium::IdleAnimation::update_skeleton(
&FishMediumSkeleton::new(), &FishMediumSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::fish_medium::RunAnimation::update_skeleton( Run(_) => anim::fish_medium::RunAnimation::update_skeleton(
&FishMediumSkeleton::new(), &FishMediumSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -555,14 +557,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::dragon::IdleAnimation::update_skeleton( Stand(_) => anim::dragon::IdleAnimation::update_skeleton(
&DragonSkeleton::new(), &DragonSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::dragon::RunAnimation::update_skeleton( Run(_) => anim::dragon::RunAnimation::update_skeleton(
&DragonSkeleton::new(), &DragonSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -610,14 +612,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::bird_small::IdleAnimation::update_skeleton( Stand(_) => anim::bird_small::IdleAnimation::update_skeleton(
&BirdSmallSkeleton::new(), &BirdSmallSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::bird_small::RunAnimation::update_skeleton( Run(_) => anim::bird_small::RunAnimation::update_skeleton(
&BirdSmallSkeleton::new(), &BirdSmallSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -665,14 +667,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::fish_small::IdleAnimation::update_skeleton( Stand(_) => anim::fish_small::IdleAnimation::update_skeleton(
&FishSmallSkeleton::new(), &FishSmallSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::fish_small::RunAnimation::update_skeleton( Run(_) => anim::fish_small::RunAnimation::update_skeleton(
&FishSmallSkeleton::new(), &FishSmallSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,
@ -720,14 +722,14 @@ impl FigureMgr {
} }
let target_base = match character.movement { let target_base = match character.movement {
Stand => anim::biped_large::IdleAnimation::update_skeleton( Stand(_) => anim::biped_large::IdleAnimation::update_skeleton(
&BipedLargeSkeleton::new(), &BipedLargeSkeleton::new(),
time, time,
state.movement_time, state.movement_time,
&mut movement_animation_rate, &mut movement_animation_rate,
skeleton_attr, skeleton_attr,
), ),
Run => anim::biped_large::RunAnimation::update_skeleton( Run(_) => anim::biped_large::RunAnimation::update_skeleton(
&BipedLargeSkeleton::new(), &BipedLargeSkeleton::new(),
(vel.0.magnitude(), time), (vel.0.magnitude(), time),
state.movement_time, state.movement_time,