Skip to content

Commit

Permalink
Merge pull request #273 from Eraden/audio
Browse files Browse the repository at this point in the history
Initial audio
  • Loading branch information
Nereuxofficial authored Jan 4, 2023
2 parents 38db1c2 + 3c279eb commit 3409424
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 93 deletions.
15 changes: 12 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
release:
strategy:
matrix:
os: [ windows-2019, ubuntu-latest ]
os: [ windows-2019, ubuntu-latest, macos-latest ]
toolchain: [ nightly ]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -41,8 +41,8 @@ jobs:
if : ${{ runner.os == 'Linux' }}
run: strip target/release/game

- name: Copy binary Linux
if: ${{ runner.os == 'Linux' }}
- name: Copy binary Linux/MacOS
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: cp target/release/game redlife

- name: Copy binary Windows
Expand All @@ -65,11 +65,20 @@ jobs:
recursive: false
dest: game_linux.zip

- name: Zip Release MacOS
if: ${{ runner.os == 'MacOS' }}
uses: vimtor/action-zip@v1
with:
files: assets redlife
recursive: false
dest: game_mac.zip

- name: Upload Release
uses: softprops/action-gh-release@v1
with:
files: |
game_windows.zip
game_linux.zip
game_mac.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Binary file added assets/Red_Planet.mp3
Binary file not shown.
31 changes: 18 additions & 13 deletions game/src/backend/gamestate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::backend::constants::{
ObjectId, COLORS, DESIRED_FPS, MAP_BORDER, RESOURCE_POSITION, TIME_POSITION,
};
use crate::backend::rlcolor::RLColor;
use crate::backend::screen::{Popup, StackCommand};
use crate::backend::screen::{Popup, ScreenCommand, StackCommand};
use crate::backend::utils::get_scale;
use crate::backend::utils::{get_draw_params, is_colliding};
use crate::backend::{error::RLError, screen::Screen};
Expand All @@ -30,7 +30,7 @@ use std::fs;
use std::fs::read_dir;
use std::path::Path;
use std::sync::mpsc::{channel, Receiver, Sender};
use tracing::info;
use tracing::{debug, info};

pub enum GameCommand {
AddItems(Vec<(Item, i32)>),
Expand Down Expand Up @@ -163,9 +163,10 @@ impl GameState {
GameState::load(true).unwrap_or_else(|_| GameState::new_with_lang(lng));
game_state.save(false)?;
let cloned_sender = self.get_screen_sender()?.clone();
self.get_screen_sender()?.send(StackCommand::Push(Box::new(
InfoScreen::new_death_screen(empty_resource, cloned_sender, game_state.lng),
)))?;
self.get_screen_sender()?
.send(StackCommand::Screen(ScreenCommand::Push(Box::new(
InfoScreen::new_death_screen(empty_resource, cloned_sender, game_state.lng),
))))?;
};
} else if self.player.resources_change.life < 0 {
self.player.resources_change.life = 0;
Expand All @@ -190,7 +191,7 @@ impl GameState {
let sender = self.get_screen_sender()?;
let popup =
Popup::new(RLColor::GREEN, send_msg_failure(lng).to_string(), 5);
sender.send(StackCommand::Popup(popup))?;
sender.send(StackCommand::Screen(ScreenCommand::Popup(popup)))?;
}
2 => {
self.player.milestone += 1;
Expand Down Expand Up @@ -358,11 +359,14 @@ impl GameState {
pub(crate) fn init(&mut self, ctx: &mut Context) -> RLResult {
info!("Loading assets");
read_dir("assets")?.for_each(|file| {
debug!("Loading asset: {:?}", file);
let file = file.unwrap();
let bytes = fs::read(file.path()).unwrap();
let name = file.file_name().into_string().unwrap();
self.assets
.insert(name, Image::from_bytes(ctx, bytes.as_slice()).unwrap());
if file.file_name().to_str().unwrap().ends_with(".png") {
let bytes = fs::read(file.path()).unwrap();
let name = file.file_name().into_string().unwrap();
self.assets
.insert(name, Image::from_bytes(ctx, bytes.as_slice()).unwrap());
}
});

if self.assets.is_empty() {
Expand Down Expand Up @@ -552,9 +556,10 @@ impl GameState {
info!("Player won the Game");
self.player.milestone += 1;
let cloned_sender = self.get_screen_sender()?.clone();
self.get_screen_sender()?.send(StackCommand::Push(Box::new(
InfoScreen::new_winning_screen(cloned_sender, lng),
)))?;
self.get_screen_sender()?
.send(StackCommand::Screen(ScreenCommand::Push(Box::new(
InfoScreen::new_winning_screen(cloned_sender, lng),
))))?;
}
_ => {}
}
Expand Down
5 changes: 3 additions & 2 deletions game/src/backend/movement.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This file contains the movement system, which is responsible for moving the player around the map and to interact with objects.
use crate::backend::constants::MOVEMENT_SPEED;
use crate::backend::gamestate::GameState;
use crate::backend::screen::{Screen, StackCommand};
use crate::backend::screen::{Screen, ScreenCommand, StackCommand};
use crate::RLResult;
use ggez::winit::event::VirtualKeyCode;
use ggez::Context;
Expand All @@ -20,7 +20,8 @@ impl GameState {
if ctx.keyboard.is_key_just_pressed(VirtualKeyCode::Escape) {
info!("Exiting...");
self.save(false)?;
self.get_screen_sender()?.send(StackCommand::Pop)?;
self.get_screen_sender()?
.send(StackCommand::Screen(ScreenCommand::Pop))?;
}
if ctx.keyboard.is_key_just_pressed(VirtualKeyCode::E) {
info!("Interacting with Area: {:?}", self.get_interactable());
Expand Down
93 changes: 54 additions & 39 deletions game/src/backend/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{draw, RLResult};
use crate::languages::Lang;
use ggez::glam::vec2;
use ggez::graphics::Color;
use ggez::mint::Vector2;
use ggez::{event, graphics, Context};
use std::fmt::Debug;
use std::sync::mpsc::{channel, Receiver, Sender};
Expand Down Expand Up @@ -45,6 +46,7 @@ pub struct ScreenStack {
popup: Vec<Popup>,
receiver: Receiver<StackCommand>,
sender: Sender<StackCommand>,
audio: crate::game_core::AudioState,
}

/// Popups are used to display information sent by the game on screen (toplevel)
Expand All @@ -55,6 +57,7 @@ pub struct Popup {
text: String,
expiration: Instant,
}

impl Popup {
/// Creates a new `Popup` from the nasa template.
/// # Arguments
Expand Down Expand Up @@ -108,7 +111,26 @@ impl Popup {
}
}
}

impl ScreenStack {
/// Creates a new `Screen stack` with a `MainMenu` screen.
/// # Returns
/// `ScreenStack` - Returns a new `ScreenStack`.
pub fn new_with_lang(lng: Lang, ctx: &mut Context) -> Self {
info!("Default Screen stack created");
let mut audio = crate::game_core::AudioState::new(ctx).unwrap();
audio.play_main_theme(ctx);

let (sender, receiver) = channel();
Self {
screens: vec![Box::new(MainMenu::new(sender.clone(), lng))],
popup: vec![],
receiver,
sender,
audio,
}
}

/// Draws all `Popups` at the top left of the screen with their given text and color
/// The popups will be removed after the given duration
/// # Arguments
Expand All @@ -122,9 +144,7 @@ impl ScreenStack {
for popup in &self.popup {
let mut text = graphics::Text::new(popup.text.clone());
text.set_scale(25.);
let dimensions = text.measure(ctx)?;
let x = dimensions.x;
let y = dimensions.y;
let Vector2 { x, y } = text.measure(ctx)?;
let rect = graphics::Mesh::new_rectangle(
ctx,
graphics::DrawMode::fill(),
Expand All @@ -151,47 +171,67 @@ impl ScreenStack {
canvas.finish(ctx)?;
Ok(())
}

/// Handles what to do with the given commands.
/// Possible commands are:
/// `Push`: Pushes a new screen on the stack,
/// `Pop`: Pops the current screen,
/// `Popup`: Adds a new popup to the stack
///
/// # Arguments
/// * `command` - The command to handle
fn process_command(&mut self, command: StackCommand) {
fn process_command(&mut self, ctx: &mut Context, command: StackCommand) {
// Match the command given back by the screen
match command {
StackCommand::Push(mut screen) => {
StackCommand::Screen(ScreenCommand::Push(mut screen)) => {
screen.set_sender(self.sender.clone());
self.screens.push(screen);
}
StackCommand::Pop => {
StackCommand::Screen(ScreenCommand::Pop) => {
if self.screens.len() == 1 {
std::process::exit(0)
} else {
// Clear our popups in order to not display them outside of the Gamestate
// Clear our popups in order to not display them outside of the `GameState`
self.popup.clear();
self.screens.pop();
};
}
StackCommand::Popup(popup) => self.popup.push(popup),
StackCommand::Screen(ScreenCommand::Popup(popup)) => self.popup.push(popup),
StackCommand::Audio(AudioCommand::Play) => {
self.audio.play_main_theme(ctx);
}
StackCommand::Audio(AudioCommand::Pause) => {
self.audio.pause_main_theme(ctx);
}
}
}

/// Removes the expired `Popup`s
fn remove_popups(&mut self) {
self.popup.retain(|popup| popup.expiration > Instant::now());
}
}

#[allow(clippy::module_name_repetitions)]
pub enum ScreenCommand {
Push(Box<dyn Screen>),
Popup(Popup),
Pop,
}

pub enum AudioCommand {
Play,
Pause,
}

/// The `StackCommand` is necessary in order to send commands back to the `Screenstack`
/// from the `Screen`.
/// # Examples
/// We can tell the `Screenstack` to push the `Gamestate` screen onto the
/// `Screenstack`
pub enum StackCommand {
Push(Box<dyn Screen>),
Popup(Popup),
Pop,
Screen(ScreenCommand),
Audio(AudioCommand),
}

impl event::EventHandler<RLError> for ScreenStack {
Expand All @@ -205,10 +245,11 @@ impl event::EventHandler<RLError> for ScreenStack {
let screen = self.screens.last_mut().expect("Failed to get a screen");
screen.update(ctx)?;
if let Ok(message) = self.receiver.try_recv() {
self.process_command(message);
self.process_command(ctx, message);
}
Ok(())
}

/// Redirect the draw command to the last screen.
/// # Arguments
/// * `ctx` - The ggez game context
Expand All @@ -222,6 +263,7 @@ impl event::EventHandler<RLError> for ScreenStack {
self.draw_popups(ctx)?;
Ok(())
}

/// Overrides the quit event so we do nothing instead of quitting the game.
/// # Arguments
/// * `ctx` - The ggez game context
Expand All @@ -231,30 +273,3 @@ impl event::EventHandler<RLError> for ScreenStack {
Ok(true)
}
}

impl ScreenStack {
/// Creates a new `Screen stack` with a `MainMenu` screen.
/// # Returns
/// `Screen stack` - Returns a new `Screen stack`.
pub fn new_with_lang(lng: Lang) -> Self {
info!("Default Screen stack created");
let (sender, receiver) = channel();
Self {
screens: vec![Box::new(MainMenu::new(sender.clone(), lng))],
popup: vec![],
receiver,
sender,
}
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_screen_stack() {
let screen_stack = ScreenStack::new_with_lang(Lang::De);
assert_eq!(1, screen_stack.screens.len());
}
}
28 changes: 28 additions & 0 deletions game/src/game_core/audio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use ggez::audio::{AudioContext, SoundSource};
use ggez::context::Has;
use ggez::{audio, Context, GameResult};

/// Audio controller responsible for managing which sound should be played now
pub struct AudioState {
/// Main theme played most of the time and interrupted by machines sounds
main: audio::Source,
}

impl AudioState {
pub fn new(ctx: &impl Has<AudioContext>) -> GameResult<AudioState> {
let data = audio::SoundData::from_bytes(include_bytes!("../../../assets/Red_Planet.mp3"));
let sound = audio::Source::from_data(ctx, data)?;
let s = AudioState { main: sound };
Ok(s)
}

/// Plays the sound multiple times
pub fn play_main_theme(&mut self, ctx: &mut Context) {
self.main.play_detached(ctx).ok();
}

/// Plays the sound multiple times
pub fn pause_main_theme(&mut self, _ctx: &mut Context) {
self.main.pause();
}
}
4 changes: 2 additions & 2 deletions game/src/game_core/event.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::backend::constants::{ObjectId, PopupType, DESIRED_FPS, SANDSTORM_CR};
use crate::backend::gamestate::GameState;
use crate::backend::screen::{Popup, StackCommand};
use crate::backend::screen::{Popup, ScreenCommand, StackCommand};
use crate::game_core::resources::Resources;
use crate::languages::{
comet_strike, informations_popup_mars, informations_popup_nasa, mars_info, nasa_info,
Expand Down Expand Up @@ -120,7 +120,7 @@ impl Event {
PopupType::Mars => Popup::mars(popup_message.to_string()),
// _ => Popup::new(Color::RED, "Error".to_string(), 10),
};
sender.send(StackCommand::Popup(popup))?;
sender.send(StackCommand::Screen(ScreenCommand::Popup(popup)))?;
info!(
"Event Popup sent: name: {}, Popup-Message: {}, Popup-Type: {:?}",
event_name,
Expand Down
Loading

0 comments on commit 3409424

Please sign in to comment.