Compare commits
2 commits
008e2d55bc
...
26729c6f61
Author | SHA1 | Date | |
---|---|---|---|
yuni | 26729c6f61 | ||
yuni | baa68240c5 |
|
@ -475,6 +475,8 @@ pub fn handle_input(
|
||||||
let player_entity = player.get_single().unwrap();
|
let player_entity = player.get_single().unwrap();
|
||||||
|
|
||||||
if keyboard_input.just_pressed(settings.key_interact) {
|
if keyboard_input.just_pressed(settings.key_interact) {
|
||||||
|
let mut done = false;
|
||||||
|
|
||||||
// Talking to people
|
// Talking to people
|
||||||
let objects: Vec<(chat::Talker, &Transform)> = q_talker
|
let objects: Vec<(chat::Talker, &Transform)> = q_talker
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -487,10 +489,12 @@ pub fn handle_input(
|
||||||
ew_conv.send(chat::StartConversationEvent {
|
ew_conv.send(chat::StartConversationEvent {
|
||||||
talker: talker.clone(),
|
talker: talker.clone(),
|
||||||
});
|
});
|
||||||
|
done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entering Vehicles
|
// Entering Vehicles
|
||||||
if q_player_drives.is_empty() {
|
if !done && q_player_drives.is_empty() {
|
||||||
// Sort vehicles by their distance to the player
|
// Sort vehicles by their distance to the player
|
||||||
let objects: Vec<((Entity, &Actor, Option<&MessageOnVehicleEntry>), &Transform)> =
|
let objects: Vec<((Entity, &Actor, Option<&MessageOnVehicleEntry>), &Transform)> =
|
||||||
q_vehicles
|
q_vehicles
|
||||||
|
|
319
src/camera.rs
319
src/camera.rs
|
@ -22,7 +22,6 @@ use bevy::transform::TransformSystem;
|
||||||
use bevy::window::PrimaryWindow;
|
use bevy::window::PrimaryWindow;
|
||||||
use bevy_xpbd_3d::plugins::sync;
|
use bevy_xpbd_3d::plugins::sync;
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
pub const INITIAL_ZOOM_LEVEL: f64 = 10.0;
|
pub const INITIAL_ZOOM_LEVEL: f64 = 10.0;
|
||||||
pub const MAX_DIST_FOR_MATCH_VELOCITY: f64 = 10000.0;
|
pub const MAX_DIST_FOR_MATCH_VELOCITY: f64 = 10000.0;
|
||||||
|
@ -541,324 +540,6 @@ pub fn apply_input_to_player(
|
||||||
accel.brake = key_input.pressed(settings.key_stop);
|
accel.brake = key_input.pressed(settings.key_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn apply_input_to_player_old(
|
|
||||||
time: Res<Time>,
|
|
||||||
mut commands: Commands,
|
|
||||||
settings: Res<var::Settings>,
|
|
||||||
jupiter_pos: Res<game::JupiterPos>,
|
|
||||||
windows: Query<&Window, With<PrimaryWindow>>,
|
|
||||||
mut mouse_events: EventReader<MouseMotion>,
|
|
||||||
key_input: Res<ButtonInput<KeyCode>>,
|
|
||||||
q_audiosinks: Query<(&audio::Sfx, &AudioSink)>,
|
|
||||||
q_target: Query<&LinearVelocity, (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>,
|
|
||||||
q_closest: Query<
|
|
||||||
(&Position, &LinearVelocity),
|
|
||||||
(
|
|
||||||
Without<hud::IsTargeted>,
|
|
||||||
Without<visual::IsEffect>,
|
|
||||||
Without<actor::PlayerCamera>,
|
|
||||||
Without<actor::Player>,
|
|
||||||
Without<actor::PlayerDrivesThis>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
mut q_playercam: Query<
|
|
||||||
(
|
|
||||||
Entity,
|
|
||||||
&Transform,
|
|
||||||
&mut actor::Engine,
|
|
||||||
&Position,
|
|
||||||
&mut LinearVelocity,
|
|
||||||
&mut ExternalTorque,
|
|
||||||
Option<&actor::PlayerDrivesThis>,
|
|
||||||
),
|
|
||||||
(With<actor::PlayerCamera>, Without<Camera>),
|
|
||||||
>,
|
|
||||||
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
|
||||||
) {
|
|
||||||
if settings.map_active || !settings.in_control() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let dt = time.delta_seconds();
|
|
||||||
let mut play_thruster_sound = false;
|
|
||||||
let mut axis_input: DVec3 = DVec3::ZERO;
|
|
||||||
|
|
||||||
let (win_res_x, win_res_y): (f32, f32);
|
|
||||||
let mut focused = true;
|
|
||||||
if let Ok(window) = &windows.get_single() {
|
|
||||||
focused = window.focused;
|
|
||||||
win_res_x = window.resolution.width();
|
|
||||||
win_res_y = window.resolution.height();
|
|
||||||
} else {
|
|
||||||
win_res_x = 1920.0;
|
|
||||||
win_res_y = 1050.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok((player_entity, player_transform, mut engine, pos, mut v, mut torque, bike)) =
|
|
||||||
q_playercam.get_single_mut()
|
|
||||||
{
|
|
||||||
let target_v: DVec3 = if let Ok(target) = q_target.get_single() {
|
|
||||||
target.0
|
|
||||||
} else {
|
|
||||||
let mut closest_distance = MAX_DIST_FOR_MATCH_VELOCITY;
|
|
||||||
let mut closest_velocity = None;
|
|
||||||
for (testpos, v) in q_closest.iter() {
|
|
||||||
let distance = (pos.0 - testpos.0).length();
|
|
||||||
if distance < closest_distance {
|
|
||||||
closest_velocity = Some(v);
|
|
||||||
closest_distance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if closest_velocity.is_some() {
|
|
||||||
closest_velocity.unwrap().0
|
|
||||||
} else {
|
|
||||||
let relative_pos = pos.0 - jupiter_pos.0;
|
|
||||||
nature::orbital_velocity(relative_pos, nature::JUPITER_MASS)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Handle key input
|
|
||||||
if focused {
|
|
||||||
if key_input.pressed(settings.key_forward) || settings.cruise_control_active {
|
|
||||||
axis_input.z += 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_back) {
|
|
||||||
axis_input.z -= 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_right) {
|
|
||||||
axis_input.x -= 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_left) {
|
|
||||||
axis_input.x += 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_up) {
|
|
||||||
axis_input.y += 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_down) {
|
|
||||||
axis_input.y -= 1.2;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_stop) {
|
|
||||||
let stop_direction = (target_v - v.0).normalize();
|
|
||||||
if stop_direction.length_squared() > 0.3 {
|
|
||||||
axis_input += 1.0
|
|
||||||
* DVec3::from(
|
|
||||||
player_transform.rotation.inverse() * stop_direction.as_vec3(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if settings.cruise_control_active {
|
|
||||||
axis_input.z += 1.2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// In typical games we would normalize the input vector so that diagonal movement is as
|
|
||||||
// fast as forward or sideways movement. But here, we merely clamp each direction to an
|
|
||||||
// absolute maximum of 1, since every thruster can be used separately. If the forward
|
|
||||||
// thrusters and the leftward thrusters are active at the same time, then of course the
|
|
||||||
// total diagonal acceleration is faster than the forward acceleration alone.
|
|
||||||
axis_input = axis_input.clamp(DVec3::splat(-1.0), DVec3::splat(1.0));
|
|
||||||
|
|
||||||
// Apply movement update
|
|
||||||
let forward_factor = engine.current_warmup
|
|
||||||
* (if axis_input.z > 0.0 {
|
|
||||||
engine.thrust_forward
|
|
||||||
} else {
|
|
||||||
engine.thrust_back
|
|
||||||
});
|
|
||||||
let right_factor = engine.thrust_sideways * engine.current_warmup;
|
|
||||||
let up_factor = engine.thrust_sideways * engine.current_warmup;
|
|
||||||
let factor = DVec3::new(right_factor as f64, up_factor as f64, forward_factor as f64);
|
|
||||||
let boost = if bike.is_none() {
|
|
||||||
engine.current_boost_factor
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
if axis_input.length_squared() > 0.003 {
|
|
||||||
engine.currently_firing = true;
|
|
||||||
let acceleration_global: DVec3 =
|
|
||||||
DVec3::from(player_transform.rotation * (axis_input * factor).as_vec3());
|
|
||||||
let mut acceleration_total: DVec3 =
|
|
||||||
(actor::ENGINE_SPEED_FACTOR * dt) as f64 * boost * acceleration_global;
|
|
||||||
let threshold = 1e-5;
|
|
||||||
if key_input.pressed(settings.key_stop) {
|
|
||||||
// Decelerate (or match velocity to target_v)
|
|
||||||
engine.currently_matching_velocity = true;
|
|
||||||
let dv = v.0 - target_v;
|
|
||||||
for i in 0..3 {
|
|
||||||
if dv[i].abs() < threshold {
|
|
||||||
v[i] = target_v[i];
|
|
||||||
} else if dv[i].signum() != (dv[i] + acceleration_total[i]).signum() {
|
|
||||||
// Almost stopped, but we overshot v=0
|
|
||||||
v[i] = target_v[i];
|
|
||||||
acceleration_total[i] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
engine.currently_matching_velocity = false;
|
|
||||||
}
|
|
||||||
// TODO: handle mass
|
|
||||||
v.0 += acceleration_total;
|
|
||||||
engine.current_warmup =
|
|
||||||
(engine.current_warmup + dt / engine.warmup_seconds).clamp(0.0, 1.0);
|
|
||||||
play_thruster_sound = true;
|
|
||||||
|
|
||||||
// Visual effect
|
|
||||||
if bike.is_none() && acceleration_total.length_squared() > 1e-4 {
|
|
||||||
let thruster_direction = acceleration_total.normalize();
|
|
||||||
let thruster_pos = pos.0 - 0.3 * thruster_direction;
|
|
||||||
let thruster_v = v.0 - boost * 5.0 * thruster_direction;
|
|
||||||
ew_effect.send(visual::SpawnEffectEvent {
|
|
||||||
duration: 2.0,
|
|
||||||
class: visual::Effects::ThrusterParticle(
|
|
||||||
Position::from(thruster_pos),
|
|
||||||
LinearVelocity::from(thruster_v),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
engine.currently_firing = false;
|
|
||||||
engine.currently_matching_velocity = false;
|
|
||||||
engine.current_warmup =
|
|
||||||
(engine.current_warmup - dt / engine.warmup_seconds).clamp(0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle mouse input and mouse-like key bindings
|
|
||||||
let mut play_reactionwheel_sound = false;
|
|
||||||
let mut mouse_delta = Vec2::ZERO;
|
|
||||||
let mut pitch_yaw_rot = Vec3::ZERO;
|
|
||||||
let sensitivity_factor = if settings.is_zooming {
|
|
||||||
settings.zoom_sensitivity_factor
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
let mouseless_sensitivity = 8.0 * sensitivity_factor;
|
|
||||||
let mouseless_rotation_sensitivity = 40.0 * sensitivity_factor;
|
|
||||||
if key_input.pressed(settings.key_mouseup) {
|
|
||||||
pitch_yaw_rot[0] -= mouseless_sensitivity;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_mousedown) {
|
|
||||||
pitch_yaw_rot[0] += mouseless_sensitivity;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_mouseleft) {
|
|
||||||
pitch_yaw_rot[1] += mouseless_sensitivity;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_mouseright) {
|
|
||||||
pitch_yaw_rot[1] -= mouseless_sensitivity;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_rotateleft) {
|
|
||||||
pitch_yaw_rot[2] -= mouseless_rotation_sensitivity;
|
|
||||||
}
|
|
||||||
if key_input.pressed(settings.key_rotateright) {
|
|
||||||
pitch_yaw_rot[2] += mouseless_rotation_sensitivity;
|
|
||||||
}
|
|
||||||
for mouse_event in mouse_events.read() {
|
|
||||||
mouse_delta += mouse_event.delta;
|
|
||||||
}
|
|
||||||
if mouse_delta != Vec2::ZERO {
|
|
||||||
if key_input.pressed(settings.key_rotate) {
|
|
||||||
pitch_yaw_rot[2] += 1000.0 * mouse_delta.x / win_res_x;
|
|
||||||
} else {
|
|
||||||
pitch_yaw_rot[0] += 1000.0 * mouse_delta.y / win_res_y;
|
|
||||||
pitch_yaw_rot[1] -= 1000.0 * mouse_delta.x / win_res_x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mouse_speed = pitch_yaw_rot.length();
|
|
||||||
let mouse_moving = mouse_speed > EPSILON32;
|
|
||||||
|
|
||||||
if mouse_moving {
|
|
||||||
play_reactionwheel_sound = true;
|
|
||||||
pitch_yaw_rot *=
|
|
||||||
settings.mouse_sensitivity * sensitivity_factor * engine.reaction_wheels;
|
|
||||||
torque.apply_torque(DVec3::from(
|
|
||||||
player_transform.rotation
|
|
||||||
* Vec3::new(pitch_yaw_rot[0], pitch_yaw_rot[1], pitch_yaw_rot[2]),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.rotation_stabilizer_active || key_input.pressed(settings.key_stop) {
|
|
||||||
commands
|
|
||||||
.entity(player_entity)
|
|
||||||
.try_insert(actor::WantsMaxRotation(mouse_speed as f64 * 0.1));
|
|
||||||
} else {
|
|
||||||
commands
|
|
||||||
.entity(player_entity)
|
|
||||||
.remove::<actor::WantsMaxRotation>();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut sinks: HashMap<audio::Sfx, &AudioSink> = HashMap::new();
|
|
||||||
for (sfx, sink) in &q_audiosinks {
|
|
||||||
sinks.insert(*sfx, sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play sound effects
|
|
||||||
if let Some(sink) = sinks.get(&audio::Sfx::ElectricMotor) {
|
|
||||||
let reactionwheel_volume = 1.5;
|
|
||||||
let volume = sink.volume();
|
|
||||||
let speed = sink.speed();
|
|
||||||
let action = pitch_yaw_rot.length_squared().powf(0.2) * 0.0005;
|
|
||||||
if play_reactionwheel_sound && !settings.mute_sfx && bike.is_some() {
|
|
||||||
sink.set_volume(
|
|
||||||
settings.volume_sfx * reactionwheel_volume * (volume + action).clamp(0.0, 1.0),
|
|
||||||
);
|
|
||||||
sink.set_speed((speed + action * 0.2).clamp(0.2, 0.5));
|
|
||||||
sink.play()
|
|
||||||
} else {
|
|
||||||
if volume <= 0.01 {
|
|
||||||
sink.pause()
|
|
||||||
} else {
|
|
||||||
sink.set_volume((volume - 0.01).clamp(0.0, 1.0));
|
|
||||||
sink.set_speed((speed - 0.03).clamp(0.2, 0.5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let sinks = vec![
|
|
||||||
(
|
|
||||||
1.0,
|
|
||||||
boost as f32,
|
|
||||||
actor::EngineType::Monopropellant,
|
|
||||||
sinks.get(&audio::Sfx::Thruster),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
actor::EngineType::Ion,
|
|
||||||
sinks.get(&audio::Sfx::Ion),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
let seconds_to_max_vol = 0.05;
|
|
||||||
let seconds_to_min_vol = 0.05;
|
|
||||||
for sink_data in sinks {
|
|
||||||
if let (vol_boost, speed, engine_type, Some(sink)) = sink_data {
|
|
||||||
if settings.mute_sfx {
|
|
||||||
sink.pause();
|
|
||||||
} else {
|
|
||||||
let volume = sink.volume();
|
|
||||||
let maxvol = settings.volume_sfx * vol_boost;
|
|
||||||
if engine.engine_type == engine_type {
|
|
||||||
if play_thruster_sound {
|
|
||||||
sink.set_speed(speed);
|
|
||||||
sink.play();
|
|
||||||
if volume < maxvol {
|
|
||||||
sink.set_volume(
|
|
||||||
(volume + dt / seconds_to_max_vol).clamp(0.0, maxvol),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sink.set_volume((volume - dt / seconds_to_min_vol).clamp(0.0, maxvol));
|
|
||||||
}
|
|
||||||
} else if volume > 0.0 {
|
|
||||||
sink.set_volume((volume - dt / seconds_to_min_vol).clamp(0.0, maxvol));
|
|
||||||
}
|
|
||||||
if volume < 0.0001 {
|
|
||||||
sink.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_map_only_object_visibility(
|
pub fn update_map_only_object_visibility(
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
q_camera: Query<&Transform, With<Camera>>,
|
q_camera: Query<&Transform, With<Camera>>,
|
||||||
|
|
Loading…
Reference in a new issue