Skip to content

Commit

Permalink
sound effects, polish
Browse files Browse the repository at this point in the history
  • Loading branch information
cxreiff committed Jul 29, 2024
1 parent 9f1b615 commit c0fb17e
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 12 deletions.
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
[package]
name = "lifecycler"
version = "0.1.9"
description = "Bevy Game Jam #5 submission. Terminal aquarium."
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0 OR CC0-1.0"
authors = ["cxreiff <[email protected]>"]
readme = "README.md"
repository = "https://github.com/cxreiff/lifecycler"
categories = ["games", "command-line-interface"]
keywords = ["bevy", "ratatui", "terminal", "tui", "aquarium"]
include = ["/src", "/assets"]

[dependencies]
bevy = "0.14.0"
Expand Down
Binary file added assets/bubble.ogg
Binary file not shown.
Binary file added assets/frame.glb
Binary file not shown.
Binary file modified assets/gravel.glb
Binary file not shown.
Binary file added assets/off.ogg
Binary file not shown.
Binary file added assets/on.ogg
Binary file not shown.
24 changes: 21 additions & 3 deletions src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ use bevy::{core_pipeline::bloom::BloomSettings, prelude::*};
use bevy_atmosphere::plugin::AtmosphereCamera;
use bevy_ratatui_render::RatatuiRenderContext;

const LIGHT_INTENSITY_DAYTIME: f32 = 800_000.;
use crate::{general::play_sfx, Flags};

const LIGHT_INTENSITY_DAYTIME: f32 = 500_000.;
const LIGHT_INTENSITY_NIGHTTIME: f32 = 500_000.;

const LIGHT_COLOR_DAYTIME: Color = Color::hsl(190., 0.5, 1.0);
const LIGHT_COLOR_NIGHTTIME: Color = Color::hsl(36., 0.2, 0.5);

const LIGHT_TRANSLATION_DAYTIME: Vec3 = Vec3::new(2., 3., 5.);
const LIGHT_TRANSLATION_DAYTIME: Vec3 = Vec3::new(1.7, 2.5, 5.);
const LIGHT_TRANSLATION_NIGHTTIME: Vec3 = Vec3::new(0., -2.5, 5.);

pub(super) fn plugin(app: &mut App) {
app.add_systems(Startup, setup_camera_system)
app.add_systems(Startup, (setup_camera_system, setup_sfx_system))
.add_systems(Update, toggle_daylight_system)
.add_event::<DaylightEvent>();
}
Expand All @@ -23,6 +25,12 @@ pub struct Daylight;
#[derive(Event, Default)]
pub struct DaylightEvent;

#[derive(Resource, Deref)]
pub struct ClickOnSound(Handle<AudioSource>);

#[derive(Resource, Deref)]
pub struct ClickOffSound(Handle<AudioSource>);

fn setup_camera_system(mut commands: Commands, ratatui_render: Res<RatatuiRenderContext>) {
commands.spawn((
Camera3dBundle {
Expand Down Expand Up @@ -53,22 +61,32 @@ fn setup_camera_system(mut commands: Commands, ratatui_render: Res<RatatuiRender
));
}

fn setup_sfx_system(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.insert_resource(ClickOnSound(asset_server.load("on.ogg")));
commands.insert_resource(ClickOffSound(asset_server.load("off.ogg")));
}

fn toggle_daylight_system(
mut commands: Commands,
camera_query: Query<(Entity, Option<&AtmosphereCamera>), With<Camera>>,
mut light_query: Query<(&mut PointLight, &mut Transform), With<Daylight>>,
mut daylight_events: EventReader<DaylightEvent>,
flags: Res<Flags>,
on_click: Res<ClickOnSound>,
off_click: Res<ClickOffSound>,
) {
for _ in daylight_events.read() {
let (camera, atmosphere) = camera_query.single();
let (mut light, mut light_transform) = light_query.single_mut();

if atmosphere.is_some() {
play_sfx(&mut commands, &off_click, &flags);
commands.entity(camera).remove::<AtmosphereCamera>();
light.intensity = LIGHT_INTENSITY_NIGHTTIME;
light.color = LIGHT_COLOR_NIGHTTIME;
light_transform.translation = LIGHT_TRANSLATION_NIGHTTIME;
} else {
play_sfx(&mut commands, &on_click, &flags);
commands.entity(camera).insert(AtmosphereCamera::default());
light.intensity = LIGHT_INTENSITY_DAYTIME;
light.color = LIGHT_COLOR_DAYTIME;
Expand Down
11 changes: 9 additions & 2 deletions src/creatures/behavior.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy::ecs::query::QueryEntityError;
use bevy::prelude::*;
use rand::SeedableRng;
use rand::{RngCore, SeedableRng};
use rand_chacha::ChaCha8Rng;

use crate::pellets::Pellet;
Expand All @@ -11,6 +11,7 @@ pub(super) fn plugin(app: &mut App) {
app.init_resource::<CreatureRng>();
}

#[derive(Debug)]
pub enum CreatureBehaviorVariant {
Debut,
Idle,
Expand Down Expand Up @@ -66,12 +67,17 @@ pub trait CreatureOperations {
self.clamp();
}

fn decide_behavior(&mut self, time: &Time, _rng: &mut CreatureRng) {
fn decide_behavior(&mut self, time: &Time, rng: &mut CreatureRng) {
self.behavior().timer.tick(time.delta());

if self.behavior().timer.just_finished() {
match self.behavior().variant {
CreatureBehaviorVariant::Idle => {
if rng.next_u32() % 9 == 0 {
self.start_seek_point(rng);
return;
}

let current_y = self.transform().rotation.y;
self.face_left();
if self.transform().rotation.y != current_y {
Expand Down Expand Up @@ -223,6 +229,7 @@ pub trait CreatureOperations {
max - Self::valid_point_buffer(),
)
.sample_interior(&mut rng.0)
+ min.midpoint(max)
}

fn valid_point_buffer() -> Vec3 {
Expand Down
22 changes: 19 additions & 3 deletions src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ fn draw_scene_system(
let _msg = &flags.msg;
let position = Rect::new(
(frame.size().width / 2 + frame.size().width.min(frame.size().height * 2) / 2)
.saturating_sub(13),
1,
11,
.saturating_sub(11 + if flags.muted { 8 } else { 0 }),
1 + (frame.size().height * 2).saturating_sub(frame.size().width) / 4,
9,
1,
);
let fps = Text::raw(format!(" fps: {value:.0} "))
Expand All @@ -49,6 +49,22 @@ fn draw_scene_system(
frame.render_widget(fps, position);
}
}

if flags.muted {
let position = Rect::new(
(frame.size().width / 2 + frame.size().width.min(frame.size().height * 2) / 2)
.saturating_sub(9),
1 + (frame.size().height * 2).saturating_sub(frame.size().width) / 4,
7,
1,
);
let fps = Text::raw(" muted ")
.alignment(Alignment::Center)
.bg(ratatui::style::Color::White)
.fg(ratatui::style::Color::Black);

frame.render_widget(fps, position);
}
})?;

Ok(())
Expand Down
11 changes: 11 additions & 0 deletions src/general.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use bevy::prelude::*;

use crate::Flags;

pub(super) fn plugin(app: &mut App) {
app.add_systems(PostUpdate, deferred_despawn_system);
}
Expand All @@ -17,3 +19,12 @@ fn deferred_despawn_system(
}
}
}

pub fn play_sfx(commands: &mut Commands, source: &Handle<AudioSource>, flags: &Flags) {
if !flags.muted {
commands.spawn(AudioBundle {
source: source.clone(),
settings: PlaybackSettings::DESPAWN,
});
}
}
8 changes: 7 additions & 1 deletion src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crossterm::event::{KeyCode, KeyEventKind, MouseButton, MouseEventKind};

use crate::{camera::DaylightEvent, pellets::PelletEvent, Flags};

const DRAGS_PER_EVENT: u32 = 2;

pub(super) fn plugin(app: &mut App) {
app.add_systems(PreUpdate, (handle_keyboard_system, handle_mouse_system))
.init_resource::<DragThreshold>();
Expand All @@ -31,6 +33,10 @@ fn handle_keyboard_system(
flags.debug = !flags.debug;
}

KeyCode::Char('m') => {
flags.muted = !flags.muted;
}

_ => {}
},
_ => {}
Expand Down Expand Up @@ -61,7 +67,7 @@ fn handle_mouse_system(
{
pellet_event.send(PelletEvent(transform));
}
**drag_threshold = 1;
**drag_threshold = DRAGS_PER_EVENT;
} else {
**drag_threshold -= 1;
}
Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::time::Duration;

use bevy::{
app::ScheduleRunnerPlugin, diagnostic::FrameTimeDiagnosticsPlugin, prelude::*,
app::ScheduleRunnerPlugin, diagnostic::FrameTimeDiagnosticsPlugin, log::LogPlugin, prelude::*,
window::ExitCondition,
};
use bevy_atmosphere::plugin::AtmospherePlugin;
Expand Down Expand Up @@ -30,6 +30,10 @@ impl Plugin for AppPlugin {
primary_window: None,
exit_condition: ExitCondition::DontExit,
close_when_requested: false,
})
.set(LogPlugin {
level: bevy::log::Level::ERROR,
..default()
}),
EmbeddedAssetPlugin::default(),
ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1. / 90.)),
Expand Down Expand Up @@ -61,5 +65,6 @@ impl Plugin for AppPlugin {
#[derive(Resource, Default)]
pub struct Flags {
debug: bool,
muted: bool,
msg: String,
}
16 changes: 15 additions & 1 deletion src/pellets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use rand_chacha::{
ChaCha8Rng,
};

use crate::{general::play_sfx, Flags};

pub(super) fn plugin(app: &mut App) {
app.add_systems(Startup, setup_pellets_system)
app.add_systems(Startup, (setup_pellets_system, setup_sfx_system))
.add_systems(
Update,
(
Expand Down Expand Up @@ -43,6 +45,9 @@ pub struct Perishable(Timer);
#[derive(Event, Deref)]
pub struct PelletEvent(pub Transform);

#[derive(Resource, Deref)]
pub struct PelletSound(Handle<AudioSource>);

fn setup_pellets_system(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
Expand All @@ -68,19 +73,28 @@ fn setup_pellets_system(
commands.insert_resource(PelletRng(seeded_rng));
}

fn setup_sfx_system(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.insert_resource(PelletSound(asset_server.load("bubble.ogg")));
}

fn create_pellets_system(
mut commands: Commands,
flags: Res<Flags>,
mut pellet_events: EventReader<PelletEvent>,
mut pellet_rng: ResMut<PelletRng>,
pellet_mesh: Res<PelletMesh>,
pellet_materials: Res<PelletMaterials>,
pellet_sound: Res<PelletSound>,
) {
for mouse_position in pellet_events.read() {
let fall_target = Vec3::new(
mouse_position.translation.x.clamp(-1.75, 1.75),
-1.7,
pellet_rng.next_u32() as f32 / u32::MAX as f32 * 0.75 - 0.25,
);

play_sfx(&mut commands, &pellet_sound, &flags);

commands.spawn((
Pellet,
PelletFalling(fall_target),
Expand Down
8 changes: 8 additions & 0 deletions src/tank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ fn setup_tank_system(
..default()
});

commands.spawn(SceneBundle {
transform: Transform::from_scale(Vec3::new(2., 2., 0.6))
.with_translation(Vec3::new(0., 0.0, 0.))
.with_rotation(Quat::from_rotation_x(0.)),
scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("embedded://frame.glb")),
..default()
});

let coral_bundle = PbrBundle {
transform: Transform::IDENTITY
.with_scale(Vec3::splat(0.35))
Expand Down

0 comments on commit c0fb17e

Please sign in to comment.