Implemented Flight

This commit is contained in:
Joshua Barretto 2020-11-03 22:46:07 +00:00
parent 9e905b297a
commit 6331ad9455
11 changed files with 79 additions and 35 deletions

View File

@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added Dutch translations
- Buff system
- Sneaking lets you be closer to enemies without being detected
- Flight
### Changed

View File

@ -460,6 +460,7 @@ magically infused items?"#,
"gameinput.acceptgroupinvite": "Accept Group Invite",
"gameinput.declinegroupinvite": "Decline Group Invite",
"gameinput.crafting": "Crafting",
"gameinput.fly": "Fly",
"gameinput.sneak": "Sneak",
"gameinput.swimdown": "Swim downwards",
"gameinput.swimup": "Swim upwards",

View File

@ -175,12 +175,13 @@ pub struct ControllerInputs {
pub jump: Input,
pub roll: Input,
pub glide: Input,
pub fly: Input, // Flying entities only
pub wall_leap: Input,
pub charge: Input,
pub climb: Option<Climb>,
pub swimup: Input,
pub swimdown: Input,
pub move_dir: Vec2<f32>,
pub move_z: f32, /* z axis (not combined with move_dir because they may have independent
* limits) */
pub look_dir: Dir,
}
@ -201,10 +202,9 @@ impl ControllerInputs {
self.jump.tick(dt);
self.roll.tick(dt);
self.glide.tick(dt);
self.fly.tick(dt);
self.wall_leap.tick(dt);
self.charge.tick(dt);
self.swimup.tick(dt);
self.swimdown.tick(dt);
}
pub fn tick_freshness(&mut self) {
@ -214,10 +214,9 @@ impl ControllerInputs {
self.jump.tick_freshness();
self.roll.tick_freshness();
self.glide.tick_freshness();
self.fly.tick_freshness();
self.wall_leap.tick_freshness();
self.charge.tick_freshness();
self.swimup.tick_freshness();
self.swimdown.tick_freshness();
}
/// Updates Controller inputs with new version received from the client
@ -228,12 +227,12 @@ impl ControllerInputs {
self.jump.update_with_new(new.jump);
self.roll.update_with_new(new.roll);
self.glide.update_with_new(new.glide);
self.fly.update_with_new(new.fly);
self.wall_leap.update_with_new(new.wall_leap);
self.charge.update_with_new(new.charge);
self.climb = new.climb;
self.swimup.update_with_new(new.swimup);
self.swimdown.update_with_new(new.swimdown);
self.move_dir = new.move_dir;
self.move_z = new.move_z;
self.look_dir = new.look_dir;
}

View File

@ -94,7 +94,7 @@ impl Route {
vol: &V,
pos: Vec3<f32>,
vel: Vec3<f32>,
traversal_cfg: TraversalConfig,
traversal_cfg: &TraversalConfig,
) -> Option<(Vec3<f32>, f32)>
where
V: BaseVol<Vox = Block> + ReadVol,
@ -364,7 +364,7 @@ impl Chaser {
} else {
self.route
.as_mut()
.and_then(|(r, _)| r.traverse(vol, pos, vel, traversal_cfg))
.and_then(|(r, _)| r.traverse(vol, pos, vel, &traversal_cfg))
}
} else {
None

View File

@ -14,6 +14,7 @@ use vek::*;
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
const BASE_HUMANOID_AIR_ACCEL: f32 = 8.0;
const BASE_FLIGHT_ACCEL: f32 = 16.0;
const BASE_HUMANOID_WATER_ACCEL: f32 = 150.0;
const BASE_HUMANOID_WATER_SPEED: f32 = 180.0;
// const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0;
@ -65,12 +66,23 @@ impl Body {
Body::QuadrupedLow(_) => 12.0,
}
}
pub fn can_fly(&self) -> bool {
match self {
Body::BirdMedium(_) => true,
Body::Dragon(_) => true,
Body::BirdSmall(_) => true,
_ => false,
}
}
}
/// Handles updating `Components` to move player based on state of `JoinData`
pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
if let Some(depth) = data.physics.in_fluid {
swim_move(data, update, efficiency, depth);
} else if data.inputs.fly.is_pressed() && !data.physics.on_ground && data.body.can_fly() {
fly_move(data, update, efficiency);
} else {
basic_move(data, update, efficiency);
}
@ -171,16 +183,31 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth:
handle_orientation(data, update, if data.physics.on_ground { 9.0 } else { 2.0 });
// Swim
if data.inputs.swimup.is_pressed() {
update.vel.0.z = (update.vel.0.z
+ data.dt.0 * GRAVITY * 4.0 * depth.clamped(0.0, 1.0).powf(3.0))
+ data.dt.0
* GRAVITY
* 4.0
* data
.inputs
.move_z
.clamped(-1.0, depth.clamped(0.0, 1.0).powf(3.0)))
.min(BASE_HUMANOID_WATER_SPEED);
}
// Swim
if data.inputs.swimdown.is_pressed() {
update.vel.0.z =
(update.vel.0.z + data.dt.0 * GRAVITY * -3.5).min(BASE_HUMANOID_WATER_SPEED);
}
/// Updates components to move entity as if it's flying
fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
// Update velocity (counteract gravity with lift)
// TODO: Do this better
update.vel.0 += Vec3::unit_z() * data.dt.0 * GRAVITY
+ Vec3::new(
data.inputs.move_dir.x,
data.inputs.move_dir.y,
data.inputs.move_z,
) * data.dt.0
* BASE_FLIGHT_ACCEL
* efficiency;
handle_orientation(data, update, 1.0);
}
/// First checks whether `primary`, `secondary` or `ability3` input is pressed,

View File

@ -283,8 +283,7 @@ impl<'a> System<'a> for Sys {
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
* speed.min(0.2 + (dist - AVG_FOLLOW_DIST) / 8.0);
inputs.jump.set_state(bearing.z > 1.5);
inputs.swimup.set_state(bearing.z > 0.5);
inputs.swimdown.set_state(bearing.z < 0.5);
inputs.move_z = bearing.z;
}
} else {
do_idle = true;
@ -388,8 +387,7 @@ impl<'a> System<'a> for Sys {
* speed
* 0.2; //Let small/slow animals flee slower than the player
inputs.jump.set_state(bearing.z > 1.5);
inputs.swimup.set_state(bearing.z > 0.5);
inputs.swimdown.set_state(bearing.z < 0.5);
inputs.move_z = bearing.z;
}
} else {
do_idle = true;
@ -530,8 +528,7 @@ impl<'a> System<'a> for Sys {
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
* speed;
inputs.jump.set_state(bearing.z > 1.5);
inputs.swimup.set_state(bearing.z > 0.5);
inputs.swimdown.set_state(bearing.z < 0.5);
inputs.move_z = bearing.z;
}
}

View File

@ -13,6 +13,7 @@ use specs::{
saveload::{Marker, MarkerAllocator},
Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage,
};
use vek::*;
// const CHARGE_COST: i32 = 200;
// const ROLL_COST: i32 = 30;
@ -72,6 +73,7 @@ impl<'a> System<'a> for Sys {
} else {
inputs.move_dir
};
inputs.move_z = inputs.move_z.clamped(-1.0, 1.0);
// Process other controller events
for event in controller.events.drain(..) {

View File

@ -7,6 +7,9 @@ pub struct KeyState {
pub down: bool,
pub climb_up: bool,
pub climb_down: bool,
pub swim_up: bool,
pub swim_down: bool,
pub fly: bool,
pub toggle_wield: bool,
pub toggle_glide: bool,
pub toggle_lantern: bool,
@ -29,6 +32,9 @@ impl Default for KeyState {
down: false,
climb_up: false,
climb_down: false,
swim_up: false,
swim_down: false,
fly: false,
toggle_wield: false,
toggle_glide: false,
toggle_lantern: false,

View File

@ -356,10 +356,10 @@ impl PlayState for SessionState {
self.inputs.jump.set_state(state);
},
Event::InputUpdate(GameInput::SwimUp, state) => {
self.inputs.swimup.set_state(state);
self.key_state.swim_up = state;
},
Event::InputUpdate(GameInput::SwimDown, state) => {
self.inputs.swimdown.set_state(state);
self.key_state.swim_down = state;
},
Event::InputUpdate(GameInput::Sit, state)
if state != self.key_state.toggle_sit =>
@ -421,6 +421,9 @@ impl PlayState for SessionState {
self.client.borrow_mut().toggle_glide();
}
}
Event::InputUpdate(GameInput::Fly, state) => {
self.key_state.fly ^= state;
},
Event::InputUpdate(GameInput::Climb, state) => {
self.key_state.climb_up = state;
},
@ -656,6 +659,9 @@ impl PlayState for SessionState {
};
self.inputs.climb = self.key_state.climb();
self.inputs.fly.set_state(self.key_state.fly);
self.inputs.move_z =
self.key_state.swim_up as i32 as f32 - self.key_state.swim_down as i32 as f32;
let mut outcomes = Vec::new();

View File

@ -136,6 +136,7 @@ impl ControlSettings {
GameInput::ClimbDown => KeyMouse::Key(VirtualKeyCode::LControl),
GameInput::SwimUp => KeyMouse::Key(VirtualKeyCode::Space),
GameInput::SwimDown => KeyMouse::Key(VirtualKeyCode::LShift),
GameInput::Fly => KeyMouse::Key(VirtualKeyCode::F),
GameInput::Sneak => KeyMouse::Key(VirtualKeyCode::LControl),
//GameInput::WallLeap => MIDDLE_CLICK_KEY,
GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G),
@ -203,6 +204,7 @@ impl Default for ControlSettings {
GameInput::ClimbDown,
GameInput::SwimUp,
GameInput::SwimDown,
GameInput::Fly,
GameInput::Sneak,
//GameInput::WallLeap,
GameInput::ToggleLantern,

View File

@ -44,6 +44,7 @@ pub enum GameInput {
ClimbDown,
SwimUp,
SwimDown,
Fly,
Sneak,
//WallLeap,
ToggleLantern,
@ -95,6 +96,7 @@ impl GameInput {
GameInput::ClimbDown => "gameinput.climbdown",
GameInput::SwimUp => "gameinput.swimup",
GameInput::SwimDown => "gameinput.swimdown",
GameInput::Fly => "gameinput.fly",
GameInput::Sneak => "gameinput.sneak",
//GameInput::WallLeap => "gameinput.wallleap",
GameInput::ToggleLantern => "gameinput.togglelantern",
@ -156,6 +158,7 @@ impl GameInput {
GameInput::ClimbDown,
GameInput::SwimUp,
GameInput::SwimDown,
GameInput::Fly,
GameInput::Sneak,
GameInput::ToggleLantern,
GameInput::Mount,