This commit is contained in:
Theis Pieter Hollebeek 2025-03-03 17:39:28 +01:00
parent 7d6822cd34
commit a19a9e9cc3
14 changed files with 949 additions and 17 deletions

867
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
rand = "0.9.0"
rodio = "0.20.1"
[dependencies.sdl2]
version = "0.37.0"

4
src/gui.rs Normal file
View File

@ -0,0 +1,4 @@
mod audio;
mod render;
pub use render::start_game;

74
src/gui/audio.rs Normal file
View 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
}

View File

@ -1,17 +1,17 @@
use crate::actions::{Action, ActionsHeld};
use crate::board::Board;
use crate::game::{CurrentTetromino, Game};
use crate::tetromino::Tetromino;
use crate::Rgb;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
use sdl2::rwops::RWops;
use sdl2::ttf::Sdl2TtfContext;
use std::time::Duration;
use super::audio::{self};
const WIDTH: i32 = 1000;
const HEIGHT: i32 = 800;
@ -119,10 +119,7 @@ fn font_texture<'font, 'a, C>(
ttf_context: &'a Sdl2TtfContext,
texture_creator: &'font TextureCreator<C>,
) -> Result<Texture<'font>, String> {
let font = ttf_context.load_font_from_rwops(
RWops::from_bytes(include_bytes!("res/josenfin_sans_regular.ttf"))?,
24,
)?;
let font = ttf_context.load_font("resources/josenfin_sans_regular.ttf", 24)?;
let game_over_text = font.render(text).solid(Color::RGB(255, 255, 255)).unwrap();
let texture = texture_creator
.create_texture_from_surface(game_over_text)
@ -161,6 +158,8 @@ pub fn start_game() -> Result<(), String> {
let mut actions = ActionsHeld::new();
let mut paused = false;
let audio_thread = audio::audio_thread();
let sdl_context = sdl2::init()?;
let ttf_context = sdl2::ttf::init().unwrap();
let video_subsystem = sdl_context.video()?;
@ -242,7 +241,10 @@ pub fn start_game() -> Result<(), String> {
&ttf_context,
)?;
} else {
game.step(&actions);
let effects = game.step(&actions);
effects
.into_iter()
.for_each(|effect| audio_thread.send(effect).unwrap());
}
canvas.present();

View File

@ -3,7 +3,7 @@ use tetromino::Tetromino;
mod actions;
mod board;
mod game;
mod sdl_impl;
mod gui;
mod tetromino;
struct Rgb(u8, u8, u8);
@ -23,5 +23,5 @@ impl Rgb {
}
fn main() {
sdl_impl::start_game();
gui::start_game().unwrap();
}