104 lines
2.4 KiB
Rust
104 lines
2.4 KiB
Rust
use bevy::{input::mouse::MouseMotion, prelude::*};
|
|
use bevy_rapier3d::prelude::*;
|
|
|
|
use crate::{components::tags::Ship, utils::input::get_mouse_delta};
|
|
|
|
pub struct ShipPlugin;
|
|
|
|
impl Plugin for ShipPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(Update, ship_controls);
|
|
#[cfg(feature = "dev-viz")]
|
|
app.add_systems(Update, ship_debug);
|
|
}
|
|
}
|
|
|
|
fn ship_controls(
|
|
ship_query: Single<(&Transform, &mut Velocity, &mut Damping), With<Ship>>,
|
|
key: Res<ButtonInput<KeyCode>>,
|
|
time: Res<Time>,
|
|
mouse_motion: EventReader<MouseMotion>,
|
|
) {
|
|
let (transform, mut vel, mut damp) = ship_query.into_inner();
|
|
|
|
let mut move_vec = Vec3::ZERO;
|
|
|
|
if key.pressed(KeyCode::KeyW) {
|
|
move_vec.z = -1.0;
|
|
} else if key.pressed(KeyCode::KeyS) {
|
|
move_vec.z = 1.0;
|
|
}
|
|
|
|
if key.pressed(KeyCode::KeyA) {
|
|
move_vec.x = -1.0;
|
|
} else if key.pressed(KeyCode::KeyD) {
|
|
move_vec.x = 1.0;
|
|
}
|
|
|
|
if key.pressed(KeyCode::Space) {
|
|
move_vec.y = 1.0;
|
|
} else if key.pressed(KeyCode::ShiftLeft) {
|
|
move_vec.y = -1.0;
|
|
}
|
|
|
|
if key.pressed(KeyCode::ControlLeft) {
|
|
damp.linear_damping = 0.8;
|
|
damp.angular_damping = 0.8;
|
|
} else {
|
|
damp.linear_damping = 0.0;
|
|
damp.angular_damping = 0.0;
|
|
}
|
|
|
|
const ROLL_SPEED: f32 = 1.0;
|
|
const DEAD_ZONE: f32 = 0.1;
|
|
const INPUT_CURVE: f32 = 3.0;
|
|
let yaw = if key.pressed(KeyCode::KeyQ) {
|
|
Vec3::Y * ROLL_SPEED
|
|
} else if key.pressed(KeyCode::KeyE) {
|
|
Vec3::Y * -ROLL_SPEED
|
|
} else {
|
|
Vec3::ZERO
|
|
};
|
|
|
|
let mouse_delta = get_mouse_delta(mouse_motion).normalize_or_zero();
|
|
let mouse_input = mouse_delta
|
|
.abs()
|
|
.map(|v| if v < DEAD_ZONE { 0.0 } else { v })
|
|
.powf(INPUT_CURVE)
|
|
* mouse_delta.signum();
|
|
|
|
let roll = Vec3::NEG_Z * mouse_input.x;
|
|
let pitch = Vec3::X * mouse_input.y;
|
|
|
|
vel.angvel += (transform.rotation * (roll + yaw + pitch)) * time.delta_secs();
|
|
|
|
move_vec = transform.rotation * move_vec.normalize_or_zero();
|
|
|
|
vel.linvel += move_vec * time.delta_secs();
|
|
}
|
|
|
|
#[cfg(feature = "dev-viz")]
|
|
fn ship_debug(mut gizmos: Gizmos, ship: Single<&Transform, With<Ship>>) {
|
|
use std::ops::Range;
|
|
|
|
let base = ship.translation.floor();
|
|
const GRID: Range<i32> = -10..10;
|
|
for x in GRID {
|
|
for y in GRID {
|
|
for z in GRID {
|
|
let p = base + Vec3::new(x as f32, y as f32, z as f32);
|
|
let color = if x == 0 && y == 0 {
|
|
LinearRgba::BLUE
|
|
} else if x == 0 && z == 0 {
|
|
LinearRgba::GREEN
|
|
} else if y == 0 && z == 0 {
|
|
LinearRgba::RED
|
|
} else {
|
|
LinearRgba::gray(0.2).with_alpha(0.2)
|
|
};
|
|
gizmos.sphere(p, 0.01, color);
|
|
}
|
|
}
|
|
}
|
|
}
|