veloren/common/src/comp/states/glide.rs

80 lines
2.6 KiB
Rust
Raw Normal View History

2019-12-26 14:43:59 +00:00
use super::{
2019-12-26 18:01:19 +00:00
ActionState::*, ClimbHandler, EcsCharacterState, EcsStateUpdate, FallHandler, MoveState::*,
StandHandler, StateHandle,
2019-12-26 14:43:59 +00:00
};
use super::{GLIDE_ACCEL, GLIDE_ANTIGRAV, GLIDE_SPEED};
use vek::{Vec2, Vec3};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct GlideHandler;
impl StateHandle for GlideHandler {
2019-12-26 18:01:19 +00:00
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
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-26 18:01:19 +00:00
// Prevent action in this state, set here
update.character.action_disabled = true;
update.character.action_state = Idle;
update.character.move_state = Glide(GlideHandler);
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);
}
// If glide button isn't held
if !ecs_data.inputs.glide.is_pressed() {
2019-12-26 18:01:19 +00:00
update.character.move_state = Fall(FallHandler);
2019-12-26 14:43:59 +00:00
return update;
}
// If there is a wall in front of character go to climb
else if let Some(_wall_dir) = ecs_data.physics.on_wall {
2019-12-26 18:01:19 +00:00
update.character.move_state = Climb(ClimbHandler);
2019-12-26 14:43:59 +00:00
return update;
}
// If on ground go to stand
if ecs_data.physics.on_ground {
2019-12-26 18:01:19 +00:00
update.character.move_state = Stand(StandHandler);
2019-12-26 14:43:59 +00:00
return update;
}
// Otherwise keep gliding
return update;
}
}