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::{
Body, CharacterState, Controller, ControllerInputs, ItemKind, PhysicsState, Stats,
};
use crate::comp::{Body, Controller, ControllerInputs, ItemKind, PhysicsState, Stats};
use specs::{Component, FlaggedStorage, HashMapStorage};
use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System};
use sphynx::{Uid, UidAllocator};
//use specs_idvs::IDVStorage;
use self::{ActionState::*, MovementState::*};
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)]
pub struct RunData;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
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)]
pub enum MovementState {
Stand(StandData),

View File

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

View File

@ -1,14 +1,12 @@
use super::movement::ROLL_DURATION;
const HUMANOID_ACCEL: f32 = 50.0;
const HUMANOID_SPEED: f32 = 120.0;
use crate::{
comp::{
self, item, projectile, ActionState,
ActionState::*,
Body, CharacterState,
CharacterState::{RunData, StandData},
ControlEvent, Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
MovementState,
MovementState::*,
PhysicsState, Projectile, Stats, Vel,
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
MovementState, MovementState::*, Ori, PhysicsState, Pos, Projectile, RunData, StandData,
Stats, Vel,
},
event::{Emitter, EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
@ -33,10 +31,12 @@ impl<'a> System<'a> for Sys {
Read<'a, EventBus<LocalEvent>>,
Read<'a, DeltaTime>,
WriteStorage<'a, CharacterState>,
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
ReadStorage<'a, Controller>,
ReadStorage<'a, Stats>,
ReadStorage<'a, Body>,
ReadStorage<'a, Vel>,
ReadStorage<'a, PhysicsState>,
ReadStorage<'a, Uid>,
ReadStorage<'a, Mounting>,
@ -50,10 +50,12 @@ impl<'a> System<'a> for Sys {
local_bus,
dt,
mut character_states,
mut positions,
mut velocities,
mut orientations,
controllers,
stats,
bodies,
velocities,
physics_states,
uids,
mountings,
@ -61,14 +63,28 @@ impl<'a> System<'a> for Sys {
) {
let mut server_emitter = server_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,
&uids,
&mut character_states,
&mut positions,
&mut velocities,
&mut orientations,
&controllers,
&stats,
&bodies,
&velocities,
&physics_states,
mountings.maybe(),
)
@ -382,7 +398,7 @@ impl<'a> System<'a> for Sys {
}
if physics.on_ground {
character.movement = Stand(Stand)
character.movement = Stand(StandData)
}
}
// Any Action + Climbing, shouldnt care about action,
@ -397,9 +413,197 @@ impl<'a> System<'a> for Sys {
}
}
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 crate::{
comp::{
CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, Stats, Vel,
CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, RunData,
StandData, Stats, Vel,
},
event::{EventBus, ServerEvent},
state::DeltaTime,
@ -105,7 +106,7 @@ impl<'a> System<'a> for Sys {
)
.join()
{
if character.movement == Run || character.movement == Stand {
if character.movement == Run(RunData) || character.movement == Stand(StandData) {
continue;
}
@ -145,7 +146,7 @@ impl<'a> System<'a> for Sys {
vel.0 += Vec2::broadcast(dt.0)
* inputs.move_dir
* 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
}
(false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => {

View File

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

View File

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