Add basic game sounds
This commit is contained in:
12
src/audio.rs
Normal file
12
src/audio.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_asset_loader::prelude::*;
|
||||
|
||||
#[derive(AssetCollection, Resource)]
|
||||
pub struct Assets {
|
||||
#[asset(path = "sounds/collision.wav")]
|
||||
pub collision: Handle<AudioSource>,
|
||||
#[asset(path = "sounds/tick.wav")]
|
||||
pub tick: Handle<AudioSource>,
|
||||
#[asset(path = "sounds/blip.wav")]
|
||||
pub blip: Handle<AudioSource>,
|
||||
}
|
||||
10
src/main.rs
10
src/main.rs
@@ -6,12 +6,14 @@ use crate::{
|
||||
ui::UiPlugin,
|
||||
};
|
||||
use bevy::{prelude::*, render::camera::ScalingMode, window::WindowResolution};
|
||||
use bevy_asset_loader::prelude::*;
|
||||
use bevy_tweening::TweeningPlugin;
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use bevy_editor_pls::prelude::*;
|
||||
|
||||
mod audio;
|
||||
mod canvas;
|
||||
mod fruit;
|
||||
mod grid;
|
||||
@@ -22,7 +24,6 @@ const ASPECT_RATIO: f32 = 16. / 9.;
|
||||
const WINDOW_WIDTH: f32 = WINDOW_HEIGHT * ASPECT_RATIO;
|
||||
const WINDOW_HEIGHT: f32 = 720.;
|
||||
const TICK_PERIOD: Duration = Duration::from_millis(125);
|
||||
const CLEAR_COLOR: Color = Color::rgba(0.15, 0.15, 0.15, 1.0);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
|
||||
enum GameState {
|
||||
@@ -38,7 +39,7 @@ struct Score(u32);
|
||||
fn main() {
|
||||
let mut app = App::new();
|
||||
|
||||
app.insert_resource(ClearColor(CLEAR_COLOR))
|
||||
app.insert_resource(ClearColor(Color::BLACK))
|
||||
.insert_resource(FixedTime::new(TICK_PERIOD))
|
||||
.insert_resource(Score(0))
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
@@ -50,6 +51,7 @@ fn main() {
|
||||
}),
|
||||
..Default::default()
|
||||
}))
|
||||
.init_collection::<audio::Assets>()
|
||||
.add_state::<GameState>()
|
||||
.add_plugin(TweeningPlugin)
|
||||
.add_plugin(SnakePlugin)
|
||||
@@ -81,10 +83,6 @@ fn setup_system(mut commands: Commands) {
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
camera: Camera {
|
||||
hdr: true,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Name::new("Orthographic Camera"));
|
||||
|
||||
71
src/snake.rs
71
src/snake.rs
@@ -3,7 +3,7 @@ mod bulge;
|
||||
mod direction;
|
||||
mod movement;
|
||||
|
||||
use crate::{fruit, grid, GameState};
|
||||
use crate::{audio, fruit, grid, GameState};
|
||||
use bevy::prelude::*;
|
||||
use direction::Direction;
|
||||
use itertools::Itertools;
|
||||
@@ -57,7 +57,24 @@ impl Plugin for SnakePlugin {
|
||||
.in_schedule(CoreSchedule::FixedUpdate)
|
||||
.in_set(SystemSet::CollisionDetection)
|
||||
.in_set(OnUpdate(GameState::InGame))
|
||||
.after(collision_system),
|
||||
.after(collision_system)
|
||||
.run_if(about_to_collide),
|
||||
)
|
||||
.add_system(
|
||||
collision_sound_system
|
||||
.run_if(in_state(GameState::InGame))
|
||||
.run_if(about_to_collide),
|
||||
)
|
||||
.add_system(
|
||||
tick_sound_system
|
||||
.in_schedule(CoreSchedule::FixedUpdate)
|
||||
.run_if(in_state(GameState::InGame))
|
||||
.run_if(not(about_to_collide)),
|
||||
)
|
||||
.add_system(
|
||||
blip_sound_system
|
||||
.in_schedule(CoreSchedule::FixedUpdate)
|
||||
.run_if(in_state(GameState::InGame)),
|
||||
)
|
||||
.add_system(direction::start_game_system.in_set(OnUpdate(GameState::Begin)))
|
||||
.add_system(direction::change_direction_system)
|
||||
@@ -104,11 +121,18 @@ struct Collision {
|
||||
|
||||
pub struct AddTailEvent;
|
||||
|
||||
fn create_snake_segment(commands: &mut Commands, grid_position: grid::Coordinate) -> Entity {
|
||||
fn create_snake_segment(
|
||||
commands: &mut Commands,
|
||||
grid_position: grid::Coordinate,
|
||||
segment_number: u32,
|
||||
) -> Entity {
|
||||
let mut color = Color::RED;
|
||||
color *= 0.99f32.powi(segment_number as _);
|
||||
|
||||
commands
|
||||
.spawn(SpriteBundle {
|
||||
sprite: Sprite {
|
||||
color: Color::RED,
|
||||
color,
|
||||
custom_size: Some(Vec2::splat(grid::SEGMENT_SIZE) * 0.9),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -122,7 +146,8 @@ fn create_snake_segment(commands: &mut Commands, grid_position: grid::Coordinate
|
||||
}
|
||||
|
||||
fn setup_snake_system(mut commands: Commands) {
|
||||
let snake_head = create_snake_segment(&mut commands, grid::Coordinate::splat(grid::SIZE / 2));
|
||||
let snake_head =
|
||||
create_snake_segment(&mut commands, grid::Coordinate::splat(grid::SIZE / 2), 0);
|
||||
|
||||
commands
|
||||
.entity(snake_head)
|
||||
@@ -164,11 +189,14 @@ fn add_tail_system(
|
||||
mut tail_event_reader: EventReader<AddTailEvent>,
|
||||
) {
|
||||
for _ in tail_event_reader.iter() {
|
||||
let segment =
|
||||
create_snake_segment(&mut commands, grid::Coordinate::splat(grid::Index::MIN / 2));
|
||||
|
||||
let (snake_entity, mut segments) = snake_query.single_mut();
|
||||
|
||||
let segment = create_snake_segment(
|
||||
&mut commands,
|
||||
grid::Coordinate::splat(grid::Index::MIN / 2),
|
||||
segments.0.len() as _,
|
||||
);
|
||||
|
||||
segments.0.push(segment);
|
||||
|
||||
commands
|
||||
@@ -232,12 +260,29 @@ fn collision_system(
|
||||
}
|
||||
}
|
||||
|
||||
fn game_over_system(
|
||||
query: Query<&Collision, With<Snake>>,
|
||||
mut next_state: ResMut<NextState<GameState>>,
|
||||
fn about_to_collide(query: Query<&Collision, With<Snake>>) -> bool {
|
||||
query.get_single().unwrap().about_to_collide
|
||||
}
|
||||
|
||||
fn game_over_system(mut next_state: ResMut<NextState<GameState>>) {
|
||||
next_state.set(GameState::End);
|
||||
}
|
||||
|
||||
fn collision_sound_system(audio: Res<Audio>, audio_assets: Res<audio::Assets>) {
|
||||
audio.play(audio_assets.collision.clone());
|
||||
}
|
||||
|
||||
fn tick_sound_system(audio: Res<Audio>, audio_assets: Res<audio::Assets>) {
|
||||
audio.play(audio_assets.tick.clone());
|
||||
}
|
||||
|
||||
fn blip_sound_system(
|
||||
audio: Res<Audio>,
|
||||
audio_assets: Res<audio::Assets>,
|
||||
mut eaten_event_reader: EventReader<fruit::EatenEvent>,
|
||||
) {
|
||||
if query.get_single().unwrap().about_to_collide {
|
||||
next_state.set(GameState::End);
|
||||
for _ in eaten_event_reader.iter() {
|
||||
audio.play(audio_assets.blip.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user