Compare commits
22 commits
c618c0e1c1
...
0f33b6e88e
Author | SHA1 | Date | |
---|---|---|---|
yuni | 0f33b6e88e | ||
yuni | 04825f467d | ||
yuni | 14991879c9 | ||
yuni | d4c8ca231a | ||
yuni | 0ea4c00151 | ||
yuni | bb95469f44 | ||
yuni | 35d9f0b4fd | ||
yuni | 6a82c185f2 | ||
yuni | a3f1f4bd73 | ||
yuni | 3a7ab8c9ac | ||
yuni | 2e35f90a19 | ||
yuni | 3cef44c4b2 | ||
yuni | 51059a2856 | ||
yuni | 86999574d1 | ||
yuni | 8fcb702623 | ||
yuni | 94bf21b340 | ||
yuni | 06c2d90228 | ||
yuni | e8e81e8e52 | ||
yuni | 8ea2d1fb21 | ||
yuni | d329d35396 | ||
yuni | 3ffcfcf522 | ||
yuni | 495a45d8c4 |
Binary file not shown.
|
@ -45,6 +45,20 @@
|
||||||
"metallicFactor":0.5158730149269104,
|
"metallicFactor":0.5158730149269104,
|
||||||
"roughnessFactor":0.841269850730896
|
"roughnessFactor":0.841269850730896
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doubleSided":true,
|
||||||
|
"name":"Black",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorFactor":[
|
||||||
|
0.016740795224905014,
|
||||||
|
0.016740795224905014,
|
||||||
|
0.016740795224905014,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"metallicFactor":0.8086956739425659,
|
||||||
|
"roughnessFactor":0.917391300201416
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"meshes":[
|
"meshes":[
|
||||||
|
@ -59,6 +73,15 @@
|
||||||
},
|
},
|
||||||
"indices":3,
|
"indices":3,
|
||||||
"material":0
|
"material":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":4,
|
||||||
|
"NORMAL":5,
|
||||||
|
"TEXCOORD_0":6
|
||||||
|
},
|
||||||
|
"indices":7,
|
||||||
|
"material":1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -80,15 +103,15 @@
|
||||||
{
|
{
|
||||||
"bufferView":0,
|
"bufferView":0,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":2761,
|
"count":1826,
|
||||||
"max":[
|
"max":[
|
||||||
0.44324639439582825,
|
0.44324639439582825,
|
||||||
0.14108650386333466,
|
0.14108650386333466,
|
||||||
0.4957937002182007
|
0.4851364195346832
|
||||||
],
|
],
|
||||||
"min":[
|
"min":[
|
||||||
-0.44725117087364197,
|
-0.44725117087364197,
|
||||||
-0.3539474904537201,
|
-0.34535348415374756,
|
||||||
-0.2795291841030121
|
-0.2795291841030121
|
||||||
],
|
],
|
||||||
"type":"VEC3"
|
"type":"VEC3"
|
||||||
|
@ -96,45 +119,103 @@
|
||||||
{
|
{
|
||||||
"bufferView":1,
|
"bufferView":1,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":2761,
|
"count":1826,
|
||||||
"type":"VEC3"
|
"type":"VEC3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bufferView":2,
|
"bufferView":2,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":2761,
|
"count":1826,
|
||||||
"type":"VEC2"
|
"type":"VEC2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bufferView":3,
|
"bufferView":3,
|
||||||
"componentType":5123,
|
"componentType":5123,
|
||||||
"count":15360,
|
"count":9984,
|
||||||
|
"type":"SCALAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":4,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":939,
|
||||||
|
"max":[
|
||||||
|
0.44324639439582825,
|
||||||
|
0.08284013718366623,
|
||||||
|
0.4957937002182007
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-0.44700509309768677,
|
||||||
|
-0.3539474904537201,
|
||||||
|
-0.20792187750339508
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":5,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":939,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":6,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":939,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":7,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":5376,
|
||||||
"type":"SCALAR"
|
"type":"SCALAR"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bufferViews":[
|
"bufferViews":[
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":33132,
|
"byteLength":21912,
|
||||||
"byteOffset":0,
|
"byteOffset":0,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":33132,
|
"byteLength":21912,
|
||||||
"byteOffset":33132,
|
"byteOffset":21912,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":22088,
|
"byteLength":14608,
|
||||||
"byteOffset":66264,
|
"byteOffset":43824,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":30720,
|
"byteLength":19968,
|
||||||
"byteOffset":88352,
|
"byteOffset":58432,
|
||||||
|
"target":34963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":11268,
|
||||||
|
"byteOffset":78400,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":11268,
|
||||||
|
"byteOffset":89668,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":7512,
|
||||||
|
"byteOffset":100936,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":10752,
|
||||||
|
"byteOffset":108448,
|
||||||
"target":34963
|
"target":34963
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -146,7 +227,7 @@
|
||||||
],
|
],
|
||||||
"buffers":[
|
"buffers":[
|
||||||
{
|
{
|
||||||
"byteLength":119072,
|
"byteLength":119200,
|
||||||
"uri":"ar_skirt_tartan.bin"
|
"uri":"ar_skirt_tartan.bin"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
293
src/actor.rs
293
src/actor.rs
|
@ -17,6 +17,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
|
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
|
||||||
const MAX_TRANSMISSION_DISTANCE: f32 = 100.0;
|
const MAX_TRANSMISSION_DISTANCE: f32 = 100.0;
|
||||||
|
@ -38,6 +39,7 @@ impl Plugin for ActorPlugin {
|
||||||
update_physics_lifeforms.run_if(game_running),
|
update_physics_lifeforms.run_if(game_running),
|
||||||
update_power.run_if(game_running),
|
update_power.run_if(game_running),
|
||||||
handle_gravity.run_if(game_running),
|
handle_gravity.run_if(game_running),
|
||||||
|
handle_wants_rotation_change.run_if(game_running),
|
||||||
handle_wants_maxrotation.run_if(game_running),
|
handle_wants_maxrotation.run_if(game_running),
|
||||||
handle_wants_maxvelocity
|
handle_wants_maxvelocity
|
||||||
.run_if(game_running)
|
.run_if(game_running)
|
||||||
|
@ -45,12 +47,23 @@ impl Plugin for ActorPlugin {
|
||||||
handle_wants_lookat.run_if(game_running).run_if(alive),
|
handle_wants_lookat.run_if(game_running).run_if(alive),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
app.add_systems(
|
||||||
|
PreUpdate,
|
||||||
|
handle_wants_acceleration
|
||||||
|
.run_if(game_running)
|
||||||
|
.run_if(alive)
|
||||||
|
.after(PhysicsSet::Sync)
|
||||||
|
.after(sync::position_to_transform),
|
||||||
|
);
|
||||||
|
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
handle_gforce
|
handle_gforce
|
||||||
.run_if(game_running)
|
.run_if(game_running)
|
||||||
|
.run_if(alive)
|
||||||
.after(PhysicsSet::Sync)
|
.after(PhysicsSet::Sync)
|
||||||
.after(sync::position_to_transform),
|
.after(sync::position_to_transform)
|
||||||
|
.after(handle_wants_acceleration),
|
||||||
);
|
);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
|
@ -149,6 +162,12 @@ impl Default for ExperiencesGForce {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct WantsAcceleration {
|
||||||
|
pub direction: DVec3,
|
||||||
|
pub brake: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Player; // Attached to the suit of the player
|
pub struct Player; // Attached to the suit of the player
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
@ -164,6 +183,8 @@ pub struct ActorEnteringVehicle;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct ActorVehicleBeingEntered;
|
pub struct ActorVehicleBeingEntered;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
pub struct HiddenInsideVehicle;
|
||||||
|
#[derive(Component)]
|
||||||
pub struct MessageOnVehicleEntry(pub String);
|
pub struct MessageOnVehicleEntry(pub String);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct PlayersFlashLight;
|
pub struct PlayersFlashLight;
|
||||||
|
@ -176,6 +197,8 @@ pub struct WantsMaxVelocity(pub f64);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct WantsToLookAt(pub String);
|
pub struct WantsToLookAt(pub String);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
pub struct WantsRotationChange(pub Vec3); // Vec3 = (pitch, yaw, rot)
|
||||||
|
#[derive(Component)]
|
||||||
pub struct WantsMatchVelocityWith(pub String);
|
pub struct WantsMatchVelocityWith(pub String);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Identifier(pub String);
|
pub struct Identifier(pub String);
|
||||||
|
@ -220,7 +243,7 @@ pub enum EngineType {
|
||||||
Ion,
|
Ion,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Copy, Clone)]
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub thrust_forward: f32,
|
pub thrust_forward: f32,
|
||||||
pub thrust_back: f32,
|
pub thrust_back: f32,
|
||||||
|
@ -575,11 +598,18 @@ pub fn handle_vehicle_enter_exit(
|
||||||
*driver_vis = Visibility::Hidden; //seems to have no effect...
|
*driver_vis = Visibility::Hidden; //seems to have no effect...
|
||||||
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::EnterVehicle));
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::EnterVehicle));
|
||||||
commands.entity(driver).remove::<PlayerCamera>();
|
commands.entity(driver).remove::<PlayerCamera>();
|
||||||
|
commands.entity(driver).remove::<WantsRotationChange>();
|
||||||
commands.entity(driver).remove::<Collider>();
|
commands.entity(driver).remove::<Collider>();
|
||||||
|
commands.entity(driver).remove::<WantsAcceleration>();
|
||||||
commands.entity(driver).insert(JustNowEnteredVehicle);
|
commands.entity(driver).insert(JustNowEnteredVehicle);
|
||||||
|
commands.entity(driver).insert(HiddenInsideVehicle);
|
||||||
|
commands
|
||||||
|
.entity(vehicle)
|
||||||
|
.insert(WantsAcceleration::default());
|
||||||
commands.entity(vehicle).remove::<hud::IsTargeted>();
|
commands.entity(vehicle).remove::<hud::IsTargeted>();
|
||||||
commands.entity(vehicle).insert(PlayerCamera);
|
commands.entity(vehicle).insert(PlayerCamera);
|
||||||
commands.entity(vehicle).insert(PlayerDrivesThis);
|
commands.entity(vehicle).insert(PlayerDrivesThis);
|
||||||
|
commands.entity(vehicle).insert(WantsMaxRotation(0.0));
|
||||||
if let Ok(mut flashlight_trans) = q_playerflashlight.get_single_mut() {
|
if let Ok(mut flashlight_trans) = q_playerflashlight.get_single_mut() {
|
||||||
flashlight_trans.rotation = Quat::from_rotation_y(0f32);
|
flashlight_trans.rotation = Quat::from_rotation_y(0f32);
|
||||||
flashlight_trans.translation = Vec3::new(0.0, 0.0, 0.0);
|
flashlight_trans.translation = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
@ -599,11 +629,16 @@ pub fn handle_vehicle_enter_exit(
|
||||||
Quat::from_rotation_y(180f32.to_radians());
|
Quat::from_rotation_y(180f32.to_radians());
|
||||||
flashlight_trans.translation = Vec3::new(0.0, 0.0, 1.0);
|
flashlight_trans.translation = Vec3::new(0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
commands.entity(driver).remove::<HiddenInsideVehicle>();
|
||||||
|
commands.entity(driver).insert(WantsAcceleration::default());
|
||||||
commands.entity(driver).insert(RigidBody::Dynamic);
|
commands.entity(driver).insert(RigidBody::Dynamic);
|
||||||
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::ExitVehicle));
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::ExitVehicle));
|
||||||
|
commands.entity(vehicle).remove::<WantsMaxRotation>();
|
||||||
commands.entity(vehicle).remove::<PlayerCamera>();
|
commands.entity(vehicle).remove::<PlayerCamera>();
|
||||||
commands.entity(driver).insert(PlayerCamera);
|
commands.entity(driver).insert(PlayerCamera);
|
||||||
commands.entity(vehicle).remove::<PlayerDrivesThis>();
|
commands.entity(vehicle).remove::<PlayerDrivesThis>();
|
||||||
|
commands.entity(vehicle).remove::<WantsAcceleration>();
|
||||||
|
commands.entity(vehicle).remove::<WantsRotationChange>();
|
||||||
*vehicle_vis = Visibility::Visible;
|
*vehicle_vis = Visibility::Visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,6 +738,260 @@ fn handle_wants_maxvelocity(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_wants_rotation_change(mut q_actor: Query<(&mut Rotation, &mut WantsRotationChange)>) {
|
||||||
|
for (mut rot, mut change_rot) in &mut q_actor {
|
||||||
|
if change_rot.0 == Vec3::ZERO {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let actual_change_rot = change_rot.0.clamp_length_max(0.10);
|
||||||
|
for axis in 0..3 {
|
||||||
|
let original = change_rot.0[axis];
|
||||||
|
change_rot.0[axis] = 0.90 * change_rot.0[axis] - actual_change_rot[axis];
|
||||||
|
if original.signum() != change_rot.0[axis].signum() {
|
||||||
|
change_rot.0[axis] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let change = DQuat::from_euler(
|
||||||
|
EulerRot::XYZ,
|
||||||
|
actual_change_rot[0] as f64,
|
||||||
|
actual_change_rot[1] as f64,
|
||||||
|
actual_change_rot[2] as f64,
|
||||||
|
);
|
||||||
|
**rot = **rot * change;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_wants_acceleration(
|
||||||
|
time: Res<Time>,
|
||||||
|
settings: Res<var::Settings>,
|
||||||
|
jupiter_pos: Res<game::JupiterPos>,
|
||||||
|
q_audiosinks: Query<(&audio::Sfx, &AudioSink)>,
|
||||||
|
mut q_actor: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
&Transform,
|
||||||
|
&Position,
|
||||||
|
&mut LinearVelocity,
|
||||||
|
Option<&mut Engine>,
|
||||||
|
Option<&WantsAcceleration>,
|
||||||
|
Option<&hud::IsTargeted>,
|
||||||
|
Option<&PlayerCamera>,
|
||||||
|
),
|
||||||
|
(Without<visual::IsEffect>, Without<HiddenInsideVehicle>),
|
||||||
|
>,
|
||||||
|
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
||||||
|
) {
|
||||||
|
let dt = time.delta_seconds();
|
||||||
|
|
||||||
|
// Vector elements: (Entity, is_player, pos)
|
||||||
|
let mut request_closest: Vec<(Entity, bool, DVec3)> = vec![];
|
||||||
|
let mut closest_map: HashMap<Entity, DVec3> = HashMap::new();
|
||||||
|
|
||||||
|
// First, determine whether any actor wants to brake (=match velocity)
|
||||||
|
for (entity, _, pos, _, _, accel, _, is_player) in &mut q_actor {
|
||||||
|
if accel.is_some() && accel.unwrap().brake {
|
||||||
|
request_closest.push((entity, is_player.is_some(), pos.0.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an actor is braking, find out relative to what it wants to brake
|
||||||
|
for (entity, is_player, pos) in &request_closest {
|
||||||
|
let mut target_v: Option<DVec3> = None;
|
||||||
|
|
||||||
|
// First, if this is the player, check whether they targeted anything
|
||||||
|
// so we can match velocity to the target.
|
||||||
|
if *is_player {
|
||||||
|
for (_, _, _, v, _, _, is_target, _) in &q_actor {
|
||||||
|
if is_target.is_some() {
|
||||||
|
target_v = Some(v.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not, simply look for the closest object and match velocity to that.
|
||||||
|
if target_v.is_none() {
|
||||||
|
let mut closest_distance = camera::MAX_DIST_FOR_MATCH_VELOCITY;
|
||||||
|
for (testentity, _, testpos, v, _, _, _, _) in &q_actor {
|
||||||
|
if *entity != testentity {
|
||||||
|
let distance = (*pos - testpos.0).length();
|
||||||
|
if distance < closest_distance {
|
||||||
|
target_v = Some(v.0);
|
||||||
|
closest_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort: Match velocity to the orbital velocity around Jupiter
|
||||||
|
if target_v.is_none() {
|
||||||
|
let relative_pos = *pos - jupiter_pos.0;
|
||||||
|
target_v = Some(nature::orbital_velocity(relative_pos, nature::JUPITER_MASS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(target_v) = target_v {
|
||||||
|
closest_map.insert(*entity, target_v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, apply the requested acceleration to the actor's velocity
|
||||||
|
let mut play_thruster_sound = false;
|
||||||
|
let mut players_engine: Option<Engine> = None;
|
||||||
|
for (entity, trans, pos, mut v, engine, accel, _, is_player) in &mut q_actor {
|
||||||
|
let mut thruster_on = false;
|
||||||
|
if let (Some(mut engine), Some(accel)) = (engine, accel) {
|
||||||
|
let mut delta_v = DVec3::ZERO;
|
||||||
|
let mut allow_fullstop = false;
|
||||||
|
let boost = engine.current_boost_factor;
|
||||||
|
engine.currently_matching_velocity = false;
|
||||||
|
|
||||||
|
if accel.brake {
|
||||||
|
if let Some(target_v) = closest_map.get(&entity) {
|
||||||
|
let stop_direction = (*target_v - v.0).as_vec3();
|
||||||
|
if stop_direction.length_squared() > 0.003 {
|
||||||
|
delta_v =
|
||||||
|
(trans.rotation.inverse() * stop_direction.normalize()).as_dvec3();
|
||||||
|
engine.currently_matching_velocity = true;
|
||||||
|
thruster_on = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if accel.direction != DVec3::ZERO {
|
||||||
|
// Player is pressing AWSD keys
|
||||||
|
let brake_factor = if accel.brake { 1.10 } else { 1.0 };
|
||||||
|
delta_v += accel.direction.normalize() * brake_factor;
|
||||||
|
} else if accel.brake {
|
||||||
|
// Player is only pressing space
|
||||||
|
allow_fullstop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if delta_v.length_squared() > 0.003 {
|
||||||
|
// Engine is firing!
|
||||||
|
thruster_on = true;
|
||||||
|
engine.current_warmup =
|
||||||
|
(engine.current_warmup + dt / engine.warmup_seconds).clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
delta_v = delta_v.clamp(DVec3::splat(-1.0), DVec3::splat(1.0));
|
||||||
|
|
||||||
|
// Adjust acceleration to what the engine can actually provide
|
||||||
|
let factor_forward = if accel.direction.z > 0.0 {
|
||||||
|
engine.thrust_forward
|
||||||
|
} else {
|
||||||
|
engine.thrust_back
|
||||||
|
};
|
||||||
|
let factor_right = engine.thrust_sideways;
|
||||||
|
let factor_up = engine.thrust_sideways;
|
||||||
|
let engine_factor = Vec3::new(factor_right, factor_up, factor_forward).as_dvec3()
|
||||||
|
* engine.current_warmup as f64
|
||||||
|
* ENGINE_SPEED_FACTOR as f64
|
||||||
|
* engine.current_boost_factor;
|
||||||
|
|
||||||
|
let final_accel =
|
||||||
|
(trans.rotation * (delta_v * engine_factor).as_vec3() * dt).as_dvec3();
|
||||||
|
|
||||||
|
// Apply acceleration to velocity
|
||||||
|
if allow_fullstop {
|
||||||
|
if let Some(target_v) = closest_map.get(&entity) {
|
||||||
|
// Prevent overshooting when matching velocity, which
|
||||||
|
// would result in oscillating acceleration back and forth
|
||||||
|
for axis in 0..3 {
|
||||||
|
let original = v[axis];
|
||||||
|
let target = target_v[axis];
|
||||||
|
v[axis] += final_accel[axis];
|
||||||
|
if (original - target).signum() != (v[axis] - target).signum() {
|
||||||
|
v[axis] = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
**v += final_accel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visual effect
|
||||||
|
if engine.engine_type == EngineType::Monopropellant {
|
||||||
|
let thruster_direction = final_accel.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 is not firing
|
||||||
|
engine.current_warmup =
|
||||||
|
(engine.current_warmup - dt / engine.warmup_seconds).clamp(0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_player.is_some() {
|
||||||
|
play_thruster_sound = thruster_on;
|
||||||
|
players_engine = Some((*engine).clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play sound effects for player acceleration
|
||||||
|
let engine = if let Some(engine) = players_engine {
|
||||||
|
engine
|
||||||
|
} else {
|
||||||
|
warn!("Failed to retrieve player's engine type for playing SFX");
|
||||||
|
Engine::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut sinks: HashMap<audio::Sfx, &AudioSink> = HashMap::new();
|
||||||
|
for (sfx, sink) in &q_audiosinks {
|
||||||
|
sinks.insert(*sfx, sink);
|
||||||
|
}
|
||||||
|
let sinks = vec![
|
||||||
|
(
|
||||||
|
1.0,
|
||||||
|
engine.current_boost_factor 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_wants_lookat(
|
fn handle_wants_lookat(
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
(
|
(
|
||||||
|
|
Binary file not shown.
102
src/camera.rs
102
src/camera.rs
|
@ -80,7 +80,10 @@ impl Plugin for CameraPlugin {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
position_to_transform
|
position_to_transform
|
||||||
.run_if(game_running)
|
// The if(game_running) condition should be there, but
|
||||||
|
// somehow everything apart of AR avatars ends up becoming
|
||||||
|
// invisible if I leave it in, so for now, we leave it out.
|
||||||
|
//.run_if(game_running)
|
||||||
.after(sync::position_to_transform)
|
.after(sync::position_to_transform)
|
||||||
.in_set(sync::SyncSet::PositionToTransform),
|
.in_set(sync::SyncSet::PositionToTransform),
|
||||||
);
|
);
|
||||||
|
@ -440,8 +443,103 @@ fn manage_player_actor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn apply_input_to_player(
|
pub fn apply_input_to_player(
|
||||||
|
mut commands: Commands,
|
||||||
|
settings: Res<var::Settings>,
|
||||||
|
mut q_player: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
&mut actor::WantsAcceleration,
|
||||||
|
Option<&mut actor::WantsRotationChange>,
|
||||||
|
),
|
||||||
|
With<actor::PlayerCamera>,
|
||||||
|
>,
|
||||||
|
mut mouse_events: EventReader<MouseMotion>,
|
||||||
|
key_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
q_windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
|
) {
|
||||||
|
let player = q_player.get_single_mut();
|
||||||
|
if player.is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (entity, mut accel, rot_change) = player.unwrap();
|
||||||
|
|
||||||
|
let (win_res_x, win_res_y): (f32, f32);
|
||||||
|
if let Ok(window) = &q_windows.get_single() {
|
||||||
|
win_res_x = window.resolution.width();
|
||||||
|
win_res_y = window.resolution.height();
|
||||||
|
} else {
|
||||||
|
win_res_x = 1920.0;
|
||||||
|
win_res_y = 1050.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine rotation delta
|
||||||
|
let mut pitch_yaw_rot = Vec3::ZERO;
|
||||||
|
let mut mouse_delta = Vec2::ZERO;
|
||||||
|
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] += mouse_delta.x / win_res_x;
|
||||||
|
} else {
|
||||||
|
pitch_yaw_rot[0] += mouse_delta.y / win_res_y;
|
||||||
|
pitch_yaw_rot[1] -= mouse_delta.x / win_res_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pitch_yaw_rot *= 2.0
|
||||||
|
* if settings.is_zooming {
|
||||||
|
settings.zoom_sensitivity_factor
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply rotation to player
|
||||||
|
if pitch_yaw_rot != Vec3::ZERO {
|
||||||
|
let rot_change_current = if let Some(rot_change) = &rot_change {
|
||||||
|
rot_change.0
|
||||||
|
} else {
|
||||||
|
Vec3::ZERO
|
||||||
|
};
|
||||||
|
let rot_target = rot_change_current + pitch_yaw_rot;
|
||||||
|
if let Some(mut rot_change) = rot_change {
|
||||||
|
rot_change.0 = rot_target;
|
||||||
|
} else {
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.try_insert(actor::WantsRotationChange(rot_target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine acceleration
|
||||||
|
let mut axis_input: DVec3 = DVec3::ZERO;
|
||||||
|
if key_input.pressed(settings.key_forward) || settings.cruise_control_active {
|
||||||
|
axis_input.z += 1.0;
|
||||||
|
}
|
||||||
|
if key_input.pressed(settings.key_back) {
|
||||||
|
axis_input.z -= 1.0;
|
||||||
|
}
|
||||||
|
if key_input.pressed(settings.key_right) {
|
||||||
|
axis_input.x -= 1.0;
|
||||||
|
}
|
||||||
|
if key_input.pressed(settings.key_left) {
|
||||||
|
axis_input.x += 1.0;
|
||||||
|
}
|
||||||
|
if key_input.pressed(settings.key_up) {
|
||||||
|
axis_input.y += 1.0;
|
||||||
|
}
|
||||||
|
if key_input.pressed(settings.key_down) {
|
||||||
|
axis_input.y -= 1.0;
|
||||||
|
}
|
||||||
|
//axis_input = axis_input.clamp(DVec3::splat(-1.0), DVec3::splat(1.0));
|
||||||
|
|
||||||
|
// Apply acceleration to player
|
||||||
|
accel.direction = axis_input;
|
||||||
|
accel.brake = key_input.pressed(settings.key_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn apply_input_to_player_old(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
|
|
|
@ -1126,7 +1126,7 @@
|
||||||
- Nothing native, anyway.
|
- Nothing native, anyway.
|
||||||
- That's all, thanks!:
|
- That's all, thanks!:
|
||||||
- Cool, anything else you wanted?
|
- Cool, anything else you wanted?
|
||||||
- goto: pig_node_main
|
- goto: entrypoint
|
||||||
- goto: pig_node_geo
|
- goto: pig_node_geo
|
||||||
- if: $pig
|
- if: $pig
|
||||||
You're pork! Yummy! I'm starving!:
|
You're pork! Yummy! I'm starving!:
|
||||||
|
|
|
@ -1134,7 +1134,9 @@ fn spawn_entities(
|
||||||
if state.is_player {
|
if state.is_player {
|
||||||
actor.insert(actor::Player);
|
actor.insert(actor::Player);
|
||||||
actor.insert(actor::PlayerCamera);
|
actor.insert(actor::PlayerCamera);
|
||||||
|
actor.insert(actor::WantsAcceleration::default());
|
||||||
actor.insert(hud::AugmentedRealityOverlayBroadcaster);
|
actor.insert(hud::AugmentedRealityOverlayBroadcaster);
|
||||||
|
//actor.insert(actor::WantsRotation(Quat::IDENTITY));
|
||||||
ew_updateavatar.send(hud::UpdateAvatarEvent);
|
ew_updateavatar.send(hud::UpdateAvatarEvent);
|
||||||
}
|
}
|
||||||
if state.is_sun {
|
if state.is_sun {
|
||||||
|
@ -1313,7 +1315,6 @@ fn spawn_entities(
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
NotShadowCaster,
|
NotShadowCaster,
|
||||||
NotShadowReceiver,
|
|
||||||
));
|
));
|
||||||
load_asset(ar_asset_name.as_str(), &mut entitycmd, &*asset_server);
|
load_asset(ar_asset_name.as_str(), &mut entitycmd, &*asset_server);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue