audio
This commit is contained in:
parent
7d6822cd34
commit
a19a9e9cc3
867
Cargo.lock
generated
867
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
|
rodio = "0.20.1"
|
||||||
|
|
||||||
[dependencies.sdl2]
|
[dependencies.sdl2]
|
||||||
version = "0.37.0"
|
version = "0.37.0"
|
||||||
|
4
src/gui.rs
Normal file
4
src/gui.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod audio;
|
||||||
|
mod render;
|
||||||
|
|
||||||
|
pub use render::start_game;
|
74
src/gui/audio.rs
Normal file
74
src/gui/audio.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
use std::{fs::File, io::BufReader, sync::mpsc};
|
||||||
|
|
||||||
|
use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink, Source};
|
||||||
|
|
||||||
|
use crate::game::SoundEffect;
|
||||||
|
|
||||||
|
fn source_from_path<P: AsRef<std::path::Path>>(path: P) -> Decoder<BufReader<File>> {
|
||||||
|
let file = BufReader::new(File::open(path).unwrap());
|
||||||
|
let source = Decoder::new(file).unwrap();
|
||||||
|
source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_audio<P: AsRef<std::path::Path>>(
|
||||||
|
stream_handle: &OutputStreamHandle,
|
||||||
|
sink: &mut Sink,
|
||||||
|
path: P,
|
||||||
|
volume: f32,
|
||||||
|
) {
|
||||||
|
let source = source_from_path(path);
|
||||||
|
*sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
sink.set_volume(volume);
|
||||||
|
sink.append(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn audio_thread() -> mpsc::Sender<SoundEffect> {
|
||||||
|
let (sender, receiver) = mpsc::channel();
|
||||||
|
|
||||||
|
let _ = std::thread::spawn(move || {
|
||||||
|
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||||
|
let music_sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
let mut hard_drop_sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
let mut line_clear_sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
let mut move_sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
let mut rotation_sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
|
||||||
|
music_sink.append(source_from_path("resources/music.ogg").repeat_infinite());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let Ok(effect) = receiver.recv() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
let base_volume = 0.5;
|
||||||
|
match effect {
|
||||||
|
SoundEffect::HardDrop => play_audio(
|
||||||
|
&stream_handle,
|
||||||
|
&mut hard_drop_sink,
|
||||||
|
"resources/hard_drop.ogg",
|
||||||
|
base_volume,
|
||||||
|
),
|
||||||
|
SoundEffect::LineClear(lines_cleared) => play_audio(
|
||||||
|
&stream_handle,
|
||||||
|
&mut line_clear_sink,
|
||||||
|
"resources/line_clear.ogg",
|
||||||
|
base_volume + (lines_cleared as f32 - 1.0) * 0.5,
|
||||||
|
),
|
||||||
|
SoundEffect::Move => play_audio(
|
||||||
|
&stream_handle,
|
||||||
|
&mut move_sink,
|
||||||
|
"resources/move.ogg",
|
||||||
|
base_volume,
|
||||||
|
),
|
||||||
|
SoundEffect::Rotation => play_audio(
|
||||||
|
&stream_handle,
|
||||||
|
&mut rotation_sink,
|
||||||
|
"resources/rotation.ogg",
|
||||||
|
base_volume,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
sender
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
use crate::actions::{Action, ActionsHeld};
|
use crate::actions::{Action, ActionsHeld};
|
||||||
use crate::board::Board;
|
use crate::board::Board;
|
||||||
use crate::game::{CurrentTetromino, Game};
|
use crate::game::{CurrentTetromino, Game};
|
||||||
use crate::tetromino::Tetromino;
|
|
||||||
use crate::Rgb;
|
use crate::Rgb;
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
||||||
use sdl2::rwops::RWops;
|
|
||||||
use sdl2::ttf::Sdl2TtfContext;
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use super::audio::{self};
|
||||||
|
|
||||||
const WIDTH: i32 = 1000;
|
const WIDTH: i32 = 1000;
|
||||||
const HEIGHT: i32 = 800;
|
const HEIGHT: i32 = 800;
|
||||||
|
|
||||||
@ -119,10 +119,7 @@ fn font_texture<'font, 'a, C>(
|
|||||||
ttf_context: &'a Sdl2TtfContext,
|
ttf_context: &'a Sdl2TtfContext,
|
||||||
texture_creator: &'font TextureCreator<C>,
|
texture_creator: &'font TextureCreator<C>,
|
||||||
) -> Result<Texture<'font>, String> {
|
) -> Result<Texture<'font>, String> {
|
||||||
let font = ttf_context.load_font_from_rwops(
|
let font = ttf_context.load_font("resources/josenfin_sans_regular.ttf", 24)?;
|
||||||
RWops::from_bytes(include_bytes!("res/josenfin_sans_regular.ttf"))?,
|
|
||||||
24,
|
|
||||||
)?;
|
|
||||||
let game_over_text = font.render(text).solid(Color::RGB(255, 255, 255)).unwrap();
|
let game_over_text = font.render(text).solid(Color::RGB(255, 255, 255)).unwrap();
|
||||||
let texture = texture_creator
|
let texture = texture_creator
|
||||||
.create_texture_from_surface(game_over_text)
|
.create_texture_from_surface(game_over_text)
|
||||||
@ -161,6 +158,8 @@ pub fn start_game() -> Result<(), String> {
|
|||||||
let mut actions = ActionsHeld::new();
|
let mut actions = ActionsHeld::new();
|
||||||
let mut paused = false;
|
let mut paused = false;
|
||||||
|
|
||||||
|
let audio_thread = audio::audio_thread();
|
||||||
|
|
||||||
let sdl_context = sdl2::init()?;
|
let sdl_context = sdl2::init()?;
|
||||||
let ttf_context = sdl2::ttf::init().unwrap();
|
let ttf_context = sdl2::ttf::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video()?;
|
let video_subsystem = sdl_context.video()?;
|
||||||
@ -242,7 +241,10 @@ pub fn start_game() -> Result<(), String> {
|
|||||||
&ttf_context,
|
&ttf_context,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
game.step(&actions);
|
let effects = game.step(&actions);
|
||||||
|
effects
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|effect| audio_thread.send(effect).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.present();
|
canvas.present();
|
@ -3,7 +3,7 @@ use tetromino::Tetromino;
|
|||||||
mod actions;
|
mod actions;
|
||||||
mod board;
|
mod board;
|
||||||
mod game;
|
mod game;
|
||||||
mod sdl_impl;
|
mod gui;
|
||||||
mod tetromino;
|
mod tetromino;
|
||||||
|
|
||||||
struct Rgb(u8, u8, u8);
|
struct Rgb(u8, u8, u8);
|
||||||
@ -23,5 +23,5 @@ impl Rgb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
sdl_impl::start_game();
|
gui::start_game().unwrap();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user