Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

Commit

Permalink
Ocean sound (#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
porkbrain authored Aug 31, 2024
1 parent 2124692 commit f103f98
Show file tree
Hide file tree
Showing 10 changed files with 82,646 additions and 1,681 deletions.
2 changes: 2 additions & 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 common/assets/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,5 @@ pub mod ui {
pub mod audio {
pub const DOOR_OPEN: &str = "audio/door_open.oga";
pub const CALL_ELEVATOR: &str = "audio/call_elevator.oga";
pub const CALM_OCEAN_LOOP: &str = "audio/calm_ocean_loop.oga";
}
84,115 changes: 82,472 additions & 1,643 deletions main_game/assets/maps/downtown.ron

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion main_game_lib/src/top_down/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::top_down::{
};

/// Use with [`IntoSystemConfigs::run_if`] to run a system only when an actor
/// moves.
/// triggers some movement event such as entering or leaving a zone.
pub fn movement_event_emitted(
) -> impl FnMut(EventReader<ActorMovementEvent>) -> bool {
on_event::<ActorMovementEvent>()
Expand Down
41 changes: 25 additions & 16 deletions main_game_lib/src/top_down/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,41 +148,50 @@ pub enum ZoneTileKind {
#[default]
Exit,

Aisle1,
Aisle2,
Aisle3,
Aisle4,

/// In interior scenes there might be multiple apartments.
/// This represents a second apartment in such scenes.
Apartment2,
Apartment2BathroomDoor,
Apartment2Door,

BasementDoor,
// Some standard zones for interior scenes.
Bed,
Door,
Elevator,
Hallway,

// Entrances to places
Building1Entrance,
ClinicEntrance,
ClinicWardEntrance,
CompoundEntrance,
Door,
Elevator,
Fridges,
FruitsAndVeggies,
GoodWater,
GoToDowntown,
Hallway,
MallEntrance,
Meditation,
PlantShopEntrance,
PlayerApartment,
PlayerDoor,
SewersEntrance,
Tea,
TowerEntrance,
TwinpeaksApartmentEntrance,

// Mall zones
Aisle1,
Aisle2,
Aisle3,
Aisle4,
Fridges,
FruitsAndVeggies,
GoodWater,

// Player apartment zones
PlayerApartment,
Meditation,
PlayerDoor,
Tea,

// Others
BasementDoor,
UpperApartmentDoor,
UpperApartmentWallHidden,
NearbyOcean,
}

/// Useful for pathfinding to prefer some tiles over others.
Expand Down
2 changes: 2 additions & 0 deletions scenes/top_down/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ devtools = [

[dependencies]
bevy_grid_squared.workspace = true
bevy_kira_audio.workspace = true
bevy.workspace = true
common_assets.workspace = true
common_loading_screen.workspace = true
common_story.workspace = true
common_visuals.workspace = true
Expand Down
98 changes: 97 additions & 1 deletion scenes/top_down/src/downtown.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bevy::render::view::RenderLayers;
use bevy_grid_squared::{sq, Square};
use bevy_kira_audio::{Audio, AudioControl, AudioInstance, AudioTween};
use common_story::Character;
use common_visuals::camera::{render_layer, MainCamera};
use main_game_lib::{
Expand All @@ -10,12 +11,14 @@ use main_game_lib::{
},
player_stats::PlayerStats,
top_down::{
actor::Who,
inspect_and_interact::{
ChangeHighlightedInspectLabelEvent,
ChangeHighlightedInspectLabelEventConsumer,
SpawnLabelBgAndTextParams, ZoneToInspectLabelEntity, LIGHT_RED,
},
npc::behaviors::PatrolSequence,
ActorMovementEvent,
},
};
use top_down::{
Expand Down Expand Up @@ -68,6 +71,12 @@ impl bevy::app::Plugin for Plugin {
.run_if(rscn::tscn_loaded_but_not_spawned::<Downtown>()),
)
.add_systems(OnExit(THIS_SCENE.leaving()), despawn)
.add_systems(
Update,
control_ocean_sound
.run_if(movement_event_emitted())
.run_if(in_scene_running_state(THIS_SCENE)),
)
.add_systems(
Update,
(
Expand Down Expand Up @@ -194,12 +203,20 @@ fn spawn(
otter_builder.insert_bundle_into(&asset_server, &mut cmd.entity(otter));
}

fn despawn(mut cmd: Commands, root: Query<Entity, With<LayoutEntity>>) {
fn despawn(
mut cmd: Commands,
root: Query<Entity, With<LayoutEntity>>,
ocean_sound: Query<Entity, With<OceanSound>>,
) {
debug!("Despawning layout entities");

let root = root.single();
cmd.entity(root).despawn_recursive();

for entity in ocean_sound.iter() {
cmd.entity(entity).despawn();
}

cmd.remove_resource::<ZoneToInspectLabelEntity>();
}

Expand Down Expand Up @@ -398,3 +415,82 @@ fn show_label_closed(
error!("Cannot find clinic entrance zone for {zone_kind:?}");
}
}

#[derive(Component)]
struct OceanSound(Handle<AudioInstance>);

fn control_ocean_sound(
mut cmd: Commands,
mut movement_events: EventReader<ActorMovementEvent>,
audio: Res<Audio>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
asset_server: Res<AssetServer>,

ocean_sound: Query<&OceanSound>,
) {
use ZoneTileKind::NearbyOcean;

for event in movement_events.read() {
match event {
// spawn a new ocean sound if we're entering the ocean zone and
// there's no ocean sound playing
ActorMovementEvent::ZoneEntered {
who:
Who {
is_player: true, ..
},
zone: TileKind::Zone(NearbyOcean),
} => {
if let Some(instance) = ocean_sound
.get_single_or_none()
// this should always be Some because we still hold the
// handle to the audio instance in [OceanSound]
.and_then(|OceanSound(h)| audio_instances.get_mut(h))
{
instance.resume(AudioTween::linear(Duration::from_secs(1)));
} else {
let ocean_sound_handle =
audio
.play(asset_server.load(
common_assets::paths::audio::CALM_OCEAN_LOOP,
))
.looped()
.handle();

cmd.spawn(OceanSound(ocean_sound_handle));

// if there was another event that wanted to work on the
// ocean sound handle, it would not work
// because we just spawned it
//
// there's a possible bug: if we enter and leave the ocean
// zone within the same frame, the ocean
// sound will not be paused
// and will keep playing until the game is scene or location
// is changed
//
// unlikely and non-critical though so we don't bother
break;
}
}

ActorMovementEvent::ZoneLeft {
who:
Who {
is_player: true, ..
},
zone: TileKind::Zone(NearbyOcean),
} => {
if let Some(instance) = ocean_sound
.get_single_or_none()
.and_then(|OceanSound(h)| audio_instances.get_mut(h))
{
instance.pause(AudioTween::linear(Duration::from_secs(3)));
}
}

// we don't care about any other event
_ => {}
}
}
}
62 changes: 42 additions & 20 deletions wiki/src/assets/scene-tile-graphs/downtown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions wiki/src/scene_downtown.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
TODO

# Ocean

When the player approaches the ocean, a background track with ocean sounds starts playing.

0 comments on commit f103f98

Please sign in to comment.