Skip to content

Commit

Permalink
Added cool laser sound effects
Browse files Browse the repository at this point in the history
  • Loading branch information
AnthonyTornetta committed Oct 16, 2023
1 parent 1625de8 commit 3e94ff6
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 39 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cosmos_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ image = { workspace = true }

bevy-inspector-egui = { workspace = true }

rand = { workspace = true }
rand_chacha = { workspace = true }
rayon = { workspace = true }
bevy_kira_audio = { workspace = true }
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
18 changes: 15 additions & 3 deletions cosmos_client/src/audio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
//! Note that this logic does rely on the `AudioReceiver` defined in kira's implementation.
use bevy::{prelude::*, utils::HashMap};
use bevy::{prelude::*, transform::commands, utils::HashMap};
use bevy_kira_audio::{prelude::*, AudioSystemSet};

/// Contains information for a specific audio emission.
Expand Down Expand Up @@ -43,6 +43,10 @@ pub struct CosmosAudioEmitter {
pub emissions: Vec<AudioEmission>,
}

#[derive(Component, Default, Debug)]
/// This flag will despawn the entity when there are no more audio emissions occuring
pub struct DespawnOnNoEmissions;

#[derive(Default, Resource, Deref, DerefMut)]
/// Fixes the issue of sounds failing to stop because of a full command queue.
///
Expand Down Expand Up @@ -159,8 +163,12 @@ fn monitor_attached_audio_sources(
}
}

fn cleanup_stopped_spacial_instances(mut emitters: Query<&mut CosmosAudioEmitter>, instances: Res<Assets<AudioInstance>>) {
for mut emitter in emitters.iter_mut() {
fn cleanup_stopped_spacial_instances(
mut emitters: Query<(Entity, &mut CosmosAudioEmitter, Option<&DespawnOnNoEmissions>)>,
instances: Res<Assets<AudioInstance>>,
mut commands: Commands,
) {
for (entity, mut emitter, despawn_when_empty) in emitters.iter_mut() {
let handles = &mut emitter.emissions;

handles.retain(|emission| {
Expand All @@ -170,6 +178,10 @@ fn cleanup_stopped_spacial_instances(mut emitters: Query<&mut CosmosAudioEmitter
true
}
});

if handles.is_empty() && despawn_when_empty.is_some() {
commands.entity(entity).despawn_recursive();
}
}
}

Expand Down
12 changes: 11 additions & 1 deletion cosmos_client/src/projectiles/lasers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use cosmos_core::{
projectiles::laser::Laser,
};

use crate::{netty::mapping::NetworkMapping, state::game_state::GameState};
use crate::{
netty::mapping::NetworkMapping, state::game_state::GameState, structure::systems::laser_cannon_system::LaserCannonSystemFiredEvent,
};

#[derive(Resource)]
struct LaserMesh(Handle<Mesh>);
Expand All @@ -25,6 +27,7 @@ fn lasers_netty(
time: Res<Time>,
network_mapping: Res<NetworkMapping>,
laser_mesh: Res<LaserMesh>,
mut event_writer: EventWriter<LaserCannonSystemFiredEvent>,
) {
while let Some(message) = client.receive_message(NettyChannelServer::LaserCannonSystem) {
let msg: ServerLaserCannonSystemMessages = cosmos_encoder::deserialize(&message).unwrap();
Expand Down Expand Up @@ -65,6 +68,13 @@ fn lasers_netty(
&mut commands,
);
}
ServerLaserCannonSystemMessages::LaserCannonSystemFired { ship_entity } => {
let Some(ship_entity) = network_mapping.client_from_server(&ship_entity) else {
continue;
};

event_writer.send(LaserCannonSystemFiredEvent(ship_entity));
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion cosmos_client/src/structure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod chunk_retreiver;
pub mod client_structure_builder;
pub mod planet;
pub mod ship;
mod systems;
pub mod systems;

pub(super) fn register(app: &mut App) {
systems::register(app);
Expand Down
106 changes: 75 additions & 31 deletions cosmos_client/src/structure/systems/laser_cannon_system.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,75 @@
use bevy::prelude::*;

// fn prepare_sound(
// asset_server: Res<AssetServer>,
// mut commands: Commands,
// mut loader: ResMut<LoadingManager>,
// mut event_writer: EventWriter<AddLoadingEvent>,
// ) {
// let id = loader.register_loader(&mut event_writer);

// commands.insert_resource(LoadingAudioHandle(asset_server.load("cosmos/sounds/sfx/thruster-running.ogg"), id));
// }

// fn check_sound_done_loading(
// handle: Option<Res<LoadingAudioHandle>>,
// asset_server: Res<AssetServer>,
// mut commands: Commands,
// mut loader: ResMut<LoadingManager>,
// mut end_writer: EventWriter<DoneLoadingEvent>,
// ) {
// if let Some(handle) = handle {
// if asset_server.get_load_state(handle.0.id()) == LoadState::Loaded {
// commands.insert_resource(ThrusterAudioHandle(handle.0.clone()));
// commands.remove_resource::<LoadingAudioHandle>();

// loader.finish_loading(handle.1, &mut end_writer);
// }
// }
// }

pub(super) fn register(_app: &mut App) {}
//! Client-side laser cannon system logic
use bevy::{asset::LoadState, prelude::*};
use bevy_kira_audio::prelude::*;
use cosmos_core::physics::location::Location;

use crate::{
asset::asset_loader::load_assets,
audio::{AudioEmission, CosmosAudioEmitter, DespawnOnNoEmissions},
state::game_state::GameState,
};

#[derive(Event)]
/// This event is fired whenever a laser cannon system is fired
pub struct LaserCannonSystemFiredEvent(pub Entity);

#[derive(Resource)]
struct LaserCannonFireHandles(Vec<Handle<AudioSource>>);

fn apply_thruster_sound(
query: Query<(&Location, &GlobalTransform)>,
mut commands: Commands,
audio: Res<Audio>,
audio_handles: Res<LaserCannonFireHandles>,
mut event_reader: EventReader<LaserCannonSystemFiredEvent>,
) {
for entity in event_reader.iter() {
let Ok((ship_location, ship_global_transform)) = query.get(entity.0) else {
continue;
};

let mut location = *ship_location;
let translation = ship_global_transform.translation();
location.last_transform_loc = Some(ship_global_transform.translation());

let idx = rand::random::<usize>() % audio_handles.0.len();

let playing_sound: Handle<AudioInstance> = audio.play(audio_handles.0[idx].clone()).handle();

commands.spawn((
CosmosAudioEmitter {
emissions: vec![AudioEmission {
instance: playing_sound,
..Default::default()
}],
..Default::default()
},
DespawnOnNoEmissions,
location,
TransformBundle::from_transform(Transform::from_translation(translation)),
));
}
}

struct LaserCannonLoadingFlag;

pub(super) fn register(app: &mut App) {
load_assets::<AudioSource, LaserCannonLoadingFlag>(
app,
GameState::PreLoading,
vec![
"cosmos/sounds/sfx/laser-fire-1.ogg",
"cosmos/sounds/sfx/laser-fire-2.ogg",
"cosmos/sounds/sfx/laser-fire-3.ogg",
],
|mut commands, handles| {
commands.insert_resource(LaserCannonFireHandles(
handles.into_iter().filter(|x| x.1 == LoadState::Loaded).map(|x| x.0).collect(),
));
},
);

app.add_event::<LaserCannonSystemFiredEvent>()
.add_systems(Update, apply_thruster_sound.run_if(in_state(GameState::Playing)));
}
2 changes: 2 additions & 0 deletions cosmos_client/src/structure/systems/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Client-side ship systems logic
pub mod laser_cannon_system;
mod player_interactions;
pub mod thruster_system;
Expand Down
4 changes: 3 additions & 1 deletion cosmos_client/src/structure/systems/thruster_system.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Client-side thruster system logic
use std::time::Duration;

use bevy::prelude::*;
Expand Down Expand Up @@ -43,7 +45,7 @@ fn apply_thruster_sound(
}
}
} else if !thrusters_off && thruster_sound_instance.is_none() {
let playing_sound: Handle<AudioInstance> = audio.play(audio_handle.0.clone()).looped().with_volume(0.1).handle();
let playing_sound: Handle<AudioInstance> = audio.play(audio_handle.0.clone()).looped().handle();

let stop_tween = AudioTween::new(Duration::from_millis(400), AudioEasing::Linear);

Expand Down
5 changes: 5 additions & 0 deletions cosmos_core/src/netty/server_laser_cannon_system_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ pub enum ServerLaserCannonSystemMessages {
/// Which entity this laser shouldn't hit (None if it should hit all)
no_hit: Option<Entity>,
},
/// Sent whenever a laser cannon system is activated
LaserCannonSystemFired {
/// The ship the system was a part of
ship_entity: Entity,
},
}
24 changes: 22 additions & 2 deletions cosmos_server/src/structure/systems/laser_cannon_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,23 @@ const LASER_SHOOT_SECONDS: f32 = 0.2;
fn update_system(
mut query: Query<(&mut LaserCannonSystem, &StructureSystem), With<SystemActive>>,
mut es_query: Query<&mut EnergyStorageSystem>,
systems: Query<(&Systems, &Structure, &Location, &GlobalTransform, &Velocity, Option<&PhysicsWorld>)>,
systems: Query<(
Entity,
&Systems,
&Structure,
&Location,
&GlobalTransform,
&Velocity,
Option<&PhysicsWorld>,
)>,
time: Res<Time>,
mut commands: Commands,
mut server: ResMut<RenetServer>,
) {
for (mut cannon_system, system) in query.iter_mut() {
if let Ok((systems, structure, location, global_transform, ship_velocity, physics_world)) = systems.get(system.structure_entity) {
if let Ok((ship_entity, systems, structure, location, global_transform, ship_velocity, physics_world)) =
systems.get(system.structure_entity)
{
if let Ok(mut energy_storage_system) = systems.query_mut(&mut es_query) {
let sec = time.elapsed_seconds();

Expand All @@ -36,8 +46,11 @@ fn update_system(

let world_id = physics_world.map(|bw| bw.world_id).unwrap_or(DEFAULT_WORLD_ID);

let mut any_fired = false;

for line in cannon_system.lines.iter() {
if energy_storage_system.get_energy() >= line.property.energy_per_shot {
any_fired = true;
energy_storage_system.decrease_energy(line.property.energy_per_shot);

let location = structure.block_world_location(line.start.coords(), global_transform, location);
Expand Down Expand Up @@ -80,6 +93,13 @@ fn update_system(
break;
}
}

if any_fired {
server.broadcast_message(
NettyChannelServer::LaserCannonSystem,
cosmos_encoder::serialize(&ServerLaserCannonSystemMessages::LaserCannonSystemFired { ship_entity }),
);
}
}
}
}
Expand Down

0 comments on commit 3e94ff6

Please sign in to comment.