From 61324ffe7af29762a27d406903c0e0a0a6b57276 Mon Sep 17 00:00:00 2001 From: hut Date: Thu, 28 Mar 2024 13:26:14 +0100 Subject: [PATCH] implement entering vehicles, variable engine parameters --- src/actor.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++----- src/audio.rs | 3 +++ src/camera.rs | 15 ++++++++++---- src/defs.txt | 2 ++ src/settings.rs | 2 ++ src/world.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/actor.rs b/src/actor.rs index b55581a..e15ee62 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -2,6 +2,7 @@ use bevy::prelude::*; use crate::{nature, settings, actor, audio, hud}; const MIN_INTERACT_DISTANCE: f32 = 30.0; +const NO_RIDE: u32 = 0; pub struct ActorPlugin; impl Plugin for ActorPlugin { @@ -40,6 +41,7 @@ pub struct Actor { pub m: f32, // mass pub v: Vec3, // velocity pub angular_momentum: Quat, + pub inside_entity: u32, } impl Default for Actor { @@ -48,12 +50,14 @@ impl Default for Actor { hp: 100.0, m: 100.0, v: Vec3::ZERO, + inside_entity: NO_RIDE, angular_momentum: Quat::from_euler(EulerRot::XYZ, 0.001, 0.01, 0.003), } } } #[derive(Component)] pub struct Player; +#[derive(Component)] pub struct PlayerDrivesThis; #[derive(Component)] pub struct PlayerInConversation; #[derive(Component)] pub struct InConversationWithPlayer; @@ -104,6 +108,27 @@ impl Default for LifeForm { fn default() -> Self { Self { adrenaline_jolt: 0.0, }}} +#[derive(Component)] +pub struct Vehicle; + +#[derive(Component)] +pub struct Engine { + pub thrust_forward: f32, + pub thrust_back: f32, + pub thrust_sideways: f32, + pub reaction_wheels: f32, +} +impl Default for Engine { + fn default() -> Self { + Self { + thrust_forward: 1.0, + thrust_back: 1.0, + thrust_sideways: 1.0, + reaction_wheels: 1.0, + } + } +} + #[derive(Component)] pub struct Suit { pub oxygen: f32, @@ -173,17 +198,20 @@ pub fn update_physics_lifeforms( } pub fn handle_input( + mut commands: Commands, keyboard_input: Res>, settings: ResMut, - query: Query<(&Talker, &Transform)>, - player: Query<&Transform, With>, + q_talker: Query<(&Talker, &Transform), Without>, + mut player: Query<(&mut Actor, &mut Transform), With>, + mut q_vehicles: Query<(Entity, &mut Visibility, &Transform), (With, Without)>, mut ew_conv: EventWriter, + mut ew_sfx: EventWriter, ) { + let mindist = MIN_INTERACT_DISTANCE * MIN_INTERACT_DISTANCE; if keyboard_input.just_pressed(settings.key_interact) { - let mindist = MIN_INTERACT_DISTANCE * MIN_INTERACT_DISTANCE; - if let Ok(player) = player.get_single() { - for (talker, transform) in &query { + if let Ok((_player_actor, player)) = player.get_single() { + for (talker, transform) in &q_talker { if transform.translation.distance_squared(player.translation) <= mindist { ew_conv.send(StartConversationEvent{talker: talker.clone()}); break; @@ -191,6 +219,20 @@ pub fn handle_input( } } } + else if keyboard_input.just_pressed(settings.key_vehicle) { + if let Ok((mut player_actor, mut player)) = player.get_single_mut() { + for (entity, mut visibility, vehicle_transform) in q_vehicles.iter_mut() { + if vehicle_transform.translation.distance_squared(player.translation) <= mindist { + player_actor.inside_entity = entity.index(); + ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::EnterVehicle)); + *player = *vehicle_transform; + *visibility = Visibility::Hidden; + commands.entity(entity).insert(PlayerDrivesThis); + break; + } + } + } + } } pub fn handle_new_conversations( diff --git a/src/audio.rs b/src/audio.rs index c204388..7c5bb8a 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -30,6 +30,7 @@ pub enum Sfx { Switch, Ping, Connect, + EnterVehicle, None, } @@ -142,6 +143,7 @@ pub fn play_sfx( Sfx::IncomingChatMessage => sound_incoming_message.0.clone(), Sfx::Ping => sound_ping.0.clone(), Sfx::Connect => sound_connect.0.clone(), + Sfx::EnterVehicle => sound_switch.0.clone(), Sfx::None => sound_ping.0.clone(), }, settings: PlaybackSettings::DESPAWN, @@ -156,6 +158,7 @@ pub fn str2sfx(sfx_label: &str) -> Sfx { "chat" => Sfx::IncomingChatMessage, "ping" => Sfx::Ping, "connect" => Sfx::Connect, + "entervehicle" => Sfx::EnterVehicle, _ => Sfx::None, }; } diff --git a/src/camera.rs b/src/camera.rs index 5c91446..356a3c6 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -52,7 +52,8 @@ fn run_camera_controller( mut mouse_events: EventReader, key_input: Res>, thruster_sound_controller: Query<&AudioSink, With>, - mut query: Query<(&mut Transform, &mut CameraController, &mut actor::Actor), With>, + q_engine: Query<&actor::Engine, With>, + mut query: Query<(&mut Transform, &mut CameraController, &mut actor::Actor, &actor::Engine), With>, ) { let dt = time.delta_seconds(); let mut play_thruster_sound = false; @@ -63,7 +64,7 @@ fn run_camera_controller( focused = window_result.unwrap().focused; } - if let Ok((mut transform, mut controller, mut actor)) = query.get_single_mut() { + if let Ok((mut transform, mut controller, mut actor, player_engine)) = query.get_single_mut() { if !controller.initialized { controller.initialized = true; transform.rotation = @@ -120,8 +121,14 @@ fn run_camera_controller( controller.velocity = Vec3::ZERO; } } - let forward = *transform.forward(); - let right = *transform.right(); + + let engine = if let Ok(engine) = q_engine.get_single() { engine } else { player_engine }; + let forward = *transform.forward() * (if axis_input.z > 0.0 { + engine.thrust_forward + } else { + engine.thrust_back + }); + let right = *transform.right() * engine.thrust_sideways; actor.v += controller.velocity.x * dt * right + controller.velocity.y * dt * Vec3::Y + controller.velocity.z * dt * forward; diff --git a/src/defs.txt b/src/defs.txt index ae4851a..d8a4f38 100644 --- a/src/defs.txt +++ b/src/defs.txt @@ -79,6 +79,8 @@ actor 3650 230 5000 asteroid1 actor 10 -30 20 bike scale 5 + vehicle yes + thrust 50 0 10 0.5 actor 10 0 70 suit name Icarus diff --git a/src/settings.rs b/src/settings.rs index 53fd3a5..a817bad 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -23,6 +23,7 @@ pub struct Settings { pub key_run: KeyCode, pub key_stop: KeyCode, pub key_interact: KeyCode, + pub key_vehicle: KeyCode, pub key_reply1: KeyCode, pub key_reply2: KeyCode, pub key_reply3: KeyCode, @@ -70,6 +71,7 @@ impl Default for Settings { key_run: KeyCode::KeyR, key_stop: KeyCode::Space, key_interact: KeyCode::KeyE, + key_vehicle: KeyCode::KeyV, key_reply1: KeyCode::Digit1, key_reply2: KeyCode::Digit2, key_reply3: KeyCode::Digit3, diff --git a/src/world.rs b/src/world.rs index 888cf1f..c94b874 100644 --- a/src/world.rs +++ b/src/world.rs @@ -90,6 +90,10 @@ pub fn setup( integrity: 0.3, ..default() }, + actor::Engine { + thrust_forward: 1.2, + ..default() + }, Camera3dBundle { camera: Camera { hdr: true, // HDR is required for bloom @@ -236,6 +240,11 @@ struct ParserState { is_lifeform: bool, is_alive: bool, is_suited: bool, + is_vehicle: bool, + thrust_forward: f32, + thrust_sideways: f32, + thrust_back: f32, + reaction_wheels: f32, // Chat fields delay: f64, @@ -249,6 +258,7 @@ struct ParserState { impl Default for ParserState { fn default() -> Self { let default_actor = actor::Actor::default(); + let default_engine = actor::Engine::default(); Self { class: DefClass::None, name: "NONAME".to_string(), @@ -263,6 +273,11 @@ impl Default for ParserState { is_lifeform: false, is_alive: false, is_suited: false, + is_vehicle: false, + thrust_forward: default_engine.thrust_forward, + thrust_sideways: default_engine.thrust_forward, + thrust_back: default_engine.thrust_back, + reaction_wheels: default_engine.reaction_wheels, delay: 0.0, text: "".to_string(), @@ -322,6 +337,13 @@ impl ParserState { conv_id: self.chat.clone(), ..default() }; + let component_vehicle = actor::Vehicle; + let component_engine = actor::Engine { + thrust_forward: self.thrust_forward, + thrust_back: self.thrust_back, + thrust_sideways: self.thrust_sideways, + reaction_wheels: self.reaction_wheels, + }; let component_suit = actor::Suit::default(); let component_model = SceneBundle { transform: Transform { @@ -364,10 +386,20 @@ impl ParserState { )); } else { - commands.spawn(( - component_actor, - component_model, - )); + if self.is_vehicle { + commands.spawn(( + component_actor, + component_model, + component_vehicle, + component_engine, + )); + } + else { + commands.spawn(( + component_actor, + component_model, + )); + } } } self.reset(); @@ -448,6 +480,9 @@ pub fn load_defs( state.is_lifeform = true; state.is_suited = true; } + ["vehicle", "yes"] => { + state.is_vehicle = true; + } ["pronoun", pronoun] => { state.pronoun = pronoun.to_string(); } @@ -482,6 +517,14 @@ pub fn load_defs( continue; } } + ["thrust", forward, back, sideways, reaction_wheels] => { + if let (Ok(forward_float), Ok(back_float), Ok(sideways_float), Ok(reaction_wheels_float)) = (forward.parse::(), back.parse::(), sideways.parse::(), reaction_wheels.parse::()) { + state.thrust_forward = forward_float; + state.thrust_back = back_float; + state.thrust_sideways = sideways_float; + state.reaction_wheels = reaction_wheels_float; + } + } // Parsing chats ["chat", chat_name] => {