2019-12-26 14:43:59 +00:00
|
|
|
use super::{GLIDE_ACCEL, GLIDE_ANTIGRAV, GLIDE_SPEED};
|
2019-12-28 16:10:39 +00:00
|
|
|
use crate::comp::{
|
|
|
|
ActionState::*, ClimbState, EcsStateData, FallState, IdleState, MoveState::*, StandState,
|
2020-01-05 18:19:09 +00:00
|
|
|
StateHandler, StateUpdate,
|
2019-12-28 16:10:39 +00:00
|
|
|
};
|
2019-12-26 14:43:59 +00:00
|
|
|
use vek::{Vec2, Vec3};
|
|
|
|
|
2020-01-05 18:19:09 +00:00
|
|
|
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-28 16:10:39 +00:00
|
|
|
pub struct GlideState;
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2020-01-05 18:19:09 +00:00
|
|
|
impl StateHandler for GlideState {
|
2020-01-05 23:17:22 +00:00
|
|
|
fn new(ecs_data: &EcsStateData) -> Self {
|
|
|
|
Self {}
|
|
|
|
}
|
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
|
|
|
let mut update = StateUpdate {
|
2019-12-26 14:43:59 +00:00
|
|
|
pos: *ecs_data.pos,
|
|
|
|
vel: *ecs_data.vel,
|
|
|
|
ori: *ecs_data.ori,
|
|
|
|
character: *ecs_data.character,
|
|
|
|
};
|
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
// Defaults for this state
|
2020-01-05 18:19:09 +00:00
|
|
|
update.character.action_state = Idle(Some(IdleState));
|
|
|
|
update.character.move_state = Glide(Some(GlideState));
|
2019-12-26 18:01:19 +00:00
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
// Move player according to movement direction vector
|
|
|
|
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
|
|
|
* ecs_data.inputs.move_dir
|
|
|
|
* if ecs_data.vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) {
|
|
|
|
GLIDE_ACCEL
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
};
|
|
|
|
|
|
|
|
// Determine orientation vector from movement direction vector
|
|
|
|
let ori_dir = Vec2::from(update.vel.0);
|
|
|
|
if ori_dir.magnitude_squared() > 0.0001
|
|
|
|
&& (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared()
|
|
|
|
> 0.001
|
|
|
|
{
|
|
|
|
update.ori.0 =
|
|
|
|
vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), 2.0 * ecs_data.dt.0);
|
|
|
|
}
|
|
|
|
|
2019-12-26 18:01:19 +00:00
|
|
|
// Apply Glide antigrav lift
|
2019-12-26 14:43:59 +00:00
|
|
|
if Vec2::<f32>::from(update.vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)
|
|
|
|
&& update.vel.0.z < 0.0
|
|
|
|
{
|
|
|
|
let lift = GLIDE_ANTIGRAV + update.vel.0.z.abs().powf(2.0) * 0.15;
|
|
|
|
update.vel.0.z += ecs_data.dt.0
|
|
|
|
* lift
|
|
|
|
* (Vec2::<f32>::from(update.vel.0).magnitude() * 0.075)
|
|
|
|
.min(1.0)
|
|
|
|
.max(0.2);
|
|
|
|
}
|
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
// If glide button isn't held, start falling
|
2019-12-26 14:43:59 +00:00
|
|
|
if !ecs_data.inputs.glide.is_pressed() {
|
2020-01-05 18:19:09 +00:00
|
|
|
update.character.move_state = Fall(Some(FallState));
|
2019-12-26 14:43:59 +00:00
|
|
|
return update;
|
|
|
|
}
|
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
// If there is a wall in front of character go to climb
|
|
|
|
if let Some(_wall_dir) = ecs_data.physics.on_wall {
|
2020-01-05 18:19:09 +00:00
|
|
|
update.character.move_state = Climb(Some(ClimbState));
|
2019-12-26 14:43:59 +00:00
|
|
|
return update;
|
|
|
|
}
|
2019-12-28 16:10:39 +00:00
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
// If on ground go to stand
|
|
|
|
if ecs_data.physics.on_ground {
|
2020-01-05 18:19:09 +00:00
|
|
|
update.character.move_state = Stand(Some(StandState));
|
2019-12-26 14:43:59 +00:00
|
|
|
return update;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise keep gliding
|
|
|
|
return update;
|
|
|
|
}
|
|
|
|
}
|