Initial commit
This commit is contained in:
128
src/player.rs
Normal file
128
src/player.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
use crate::{
|
||||
game::{GameState, WorldEntity},
|
||||
maze::{self, Maze},
|
||||
settings::Settings,
|
||||
};
|
||||
use bevy::{
|
||||
input::mouse::AccumulatedMouseMotion,
|
||||
prelude::*,
|
||||
window::{CursorGrabMode, CursorOptions},
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Player {
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub distance: f32,
|
||||
}
|
||||
pub const SPAWN_YAW: f32 = std::f32::consts::FRAC_PI_2;
|
||||
pub fn spawn(mut commands: Commands, maze: Res<Maze>, settings: Res<Settings>) {
|
||||
commands.spawn((
|
||||
WorldEntity,
|
||||
Player {
|
||||
yaw: SPAWN_YAW,
|
||||
pitch: 0.,
|
||||
distance: 0.,
|
||||
},
|
||||
Camera3d::default(),
|
||||
bevy::render::view::NoIndirectDrawing,
|
||||
bevy::core_pipeline::tonemapping::Tonemapping::None,
|
||||
if settings.low {
|
||||
Msaa::Off
|
||||
} else {
|
||||
Msaa::Sample4
|
||||
},
|
||||
Projection::Perspective(PerspectiveProjection {
|
||||
fov: 80_f32.to_radians(),
|
||||
near: 0.05,
|
||||
far: 90.,
|
||||
..default()
|
||||
}),
|
||||
Transform::from_translation(maze::position(maze.spawn()) + Vec3::Y * 1.15)
|
||||
.with_rotation(Quat::from_rotation_y(SPAWN_YAW)),
|
||||
));
|
||||
}
|
||||
pub fn cursor(state: Res<State<GameState>>, mut windows: Query<(&Window, &mut CursorOptions)>) {
|
||||
for (window, mut c) in &mut windows {
|
||||
let grab = *state.get() == GameState::Playing && window.focused;
|
||||
c.visible = !grab;
|
||||
c.grab_mode = if grab {
|
||||
CursorGrabMode::Locked
|
||||
} else {
|
||||
CursorGrabMode::None
|
||||
};
|
||||
}
|
||||
}
|
||||
pub fn move_player(
|
||||
time: Res<Time>,
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
mouse: Res<AccumulatedMouseMotion>,
|
||||
pads: Query<&Gamepad>,
|
||||
settings: Res<Settings>,
|
||||
maze: Res<Maze>,
|
||||
mut players: Query<(&mut Player, &mut Transform)>,
|
||||
) {
|
||||
let dt = time.delta_secs().min(0.1);
|
||||
for (mut p, mut t) in &mut players {
|
||||
let mut walk = Vec2::ZERO;
|
||||
if keys.pressed(KeyCode::KeyW) {
|
||||
walk.y += 1.;
|
||||
}
|
||||
if keys.pressed(KeyCode::KeyS) {
|
||||
walk.y -= 1.;
|
||||
}
|
||||
if keys.pressed(KeyCode::KeyD) {
|
||||
walk.x += 1.;
|
||||
}
|
||||
if keys.pressed(KeyCode::KeyA) {
|
||||
walk.x -= 1.;
|
||||
}
|
||||
let mut turn = Vec2::ZERO;
|
||||
if keys.pressed(KeyCode::ArrowLeft) {
|
||||
turn.x -= 1.;
|
||||
}
|
||||
if keys.pressed(KeyCode::ArrowRight) {
|
||||
turn.x += 1.;
|
||||
}
|
||||
for pad in &pads {
|
||||
let left = pad.left_stick();
|
||||
if left.length() > 0.18 {
|
||||
walk += left;
|
||||
}
|
||||
let right = pad.right_stick();
|
||||
if right.length() > 0.18 {
|
||||
turn += Vec2::new(right.x, -right.y);
|
||||
}
|
||||
}
|
||||
p.yaw -= turn.x * dt * 2.;
|
||||
p.pitch = (p.pitch - turn.y * dt * 1.5).clamp(-1.1, 1.1);
|
||||
if !settings.keyboard_only {
|
||||
p.yaw -= mouse.delta.x * settings.sensitivity;
|
||||
p.pitch = (p.pitch - mouse.delta.y * settings.sensitivity).clamp(-1.1, 1.1);
|
||||
}
|
||||
let rotation = Quat::from_rotation_y(p.yaw);
|
||||
let velocity =
|
||||
rotation * Vec3::new(walk.x, 0., -walk.y).clamp_length_max(1.) * settings.speed * dt;
|
||||
// Small swept substeps prevent tunneling even after a long frame.
|
||||
let steps = (velocity.length() / 0.08).ceil().max(1.) as u32;
|
||||
let delta = velocity / steps as f32;
|
||||
for _ in 0..steps {
|
||||
let x = t.translation + Vec3::X * delta.x;
|
||||
if maze.fits(x, 0.25) {
|
||||
t.translation = x;
|
||||
}
|
||||
let z = t.translation + Vec3::Z * delta.z;
|
||||
if maze.fits(z, 0.25) {
|
||||
t.translation = z;
|
||||
}
|
||||
}
|
||||
p.distance += velocity.length();
|
||||
t.translation.y = 1.15
|
||||
+ if settings.bob && !settings.low {
|
||||
(p.distance * 7.).sin() * 0.025
|
||||
} else {
|
||||
0.
|
||||
};
|
||||
t.rotation = rotation * Quat::from_rotation_x(p.pitch);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user