reworking sound system

This commit is contained in:
2024-10-16 17:34:14 +02:00
parent d8298f6661
commit d2597784d4
7 changed files with 193 additions and 64 deletions

View File

@@ -3,8 +3,10 @@ cmake_minimum_required(VERSION 3.5)
project(SDL_TD VERSION 0.1 LANGUAGES CXX)
# Find SDL2
find_package(SDL2 QUIET)
find_package(SDL2 REQUIRED)
find_package(SDL2_mixer REQUIRED)
find_package(SDL2_image REQUIRED)
find_package(SDL2_ttf REQUIRED)
# Set SDL include directories and libraries
set(SDL_INCLUDE_DIRS ${SDL2_INCLUDE_DIRS})

View File

@@ -1,6 +1,6 @@
#include "Game.hpp"
Game::Game( ) : window(nullptr, SDL_DestroyWindow) { }
Game::Game( ) : window(nullptr, SDL_DestroyWindow), sound(make_unique<Sound>( )) { }
bool Game::init(const char* title, int w, int h) {
window.reset(SDL_CreateWindow(
@@ -34,15 +34,6 @@ bool Game::init(const char* title, int w, int h) {
handleWindowResize( );
bgm = std::shared_ptr<Mix_Music>(Mix_LoadMUS("assets/sound_tracks/bgm.mp3"), [ ](Mix_Music* m) {
Mix_FreeMusic(m);
});
if (!bgm) {
SDL_Log("Failed to load background music: %s", Mix_GetError( ));
return false;
}
return true;
}
@@ -53,7 +44,7 @@ void Game::run( ) {
gameRenderer->renderStartScreen( );
}
Mix_PlayMusic(bgm.get( ), -1);
sound->PlayMusic(MusicName::MAIN_THEME);
lastUpdateTime = SDL_GetTicks( );
while (!gameState.gameover && !gameBoard->isCollision( )) {
@@ -62,15 +53,10 @@ void Game::run( ) {
update( );
render( );
}
gameState.gameover = true;
Mix_PauseMusic( );
Mix_Chunk* game_over = Mix_LoadWAV("assets/sound_effects/game_over.wav");
if (game_over == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, game_over, 0);
}
gameState.gameover = true;
sound->PauseMusic( );
sound->PlaySound(SoundName::GAME_OVER);
while (gameState.gameover) {
if (gameState.quit) return;
@@ -83,7 +69,6 @@ void Game::run( ) {
void Game::inputHandler( ) {
SDL_Event event;
Mix_Chunk* movePieceSound = Mix_LoadWAV("assets/sound_effects/move_piece.wav");
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_Quit( );
@@ -93,43 +78,33 @@ void Game::inputHandler( ) {
case SDLK_LEFT:
case SDLK_a:
if (!gameState.gameover && !gameState.startSequence)
gameBoard->tryMoveCurrentTetromino(-1, 0);
if (movePieceSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, movePieceSound, 0);
}
if (gameBoard->tryMoveCurrentTetromino(-1, 0))
sound->PlaySound(SoundName::MOVE_PIECE);
break;
case SDLK_RIGHT:
case SDLK_d:
if (!gameState.gameover && !gameState.startSequence)
gameBoard->tryMoveCurrentTetromino(1, 0);
if (movePieceSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, movePieceSound, 0);
}
if (gameBoard->tryMoveCurrentTetromino(1, 0))
sound->PlaySound(SoundName::MOVE_PIECE);
break;
case SDLK_DOWN:
case SDLK_s:
if (!gameState.gameover && !gameState.startSequence)
if (!gameState.gameover && !gameState.startSequence) {
gameBoard->moveToBottom( );
sound->PlaySound(SoundName::PIECE_LANDED);
}
break;
case SDLK_SPACE:
if (!gameState.gameover && !gameState.startSequence)
gameBoard->tryRotateCurrentTetromino( );
if (gameBoard->tryRotateCurrentTetromino( ))
sound->PlaySound(SoundName::ROTATE_PIECE);
break;
case SDLK_ESCAPE:
break;
case SDLK_g:
if (gameState.startSequence) {
gameState.startSequence = false;
Mix_Chunk* menuSound = Mix_LoadWAV("assets/sound_effects/menu.wav");
if (menuSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, menuSound, 0);
}
sound->PlaySound(SoundName::MENU);
}
break;
case SDLK_r:
@@ -149,11 +124,10 @@ void Game::inputHandler( ) {
Mix_VolumeMusic(Mix_GetMusicVolume(bgm.get( )) - 8);
break;
case SDLK_m:
if (Mix_PausedMusic( ))
Mix_ResumeMusic( );
if (true)
sound->ResumeMusic( );
else
Mix_PauseMusic( );
sound->PauseMusic( );
break;
default:
break;

View File

@@ -9,6 +9,7 @@ extern "C" {
#include "Renderer.hpp"
#include "GameBoard.hpp"
#include "Sound.hpp"
using namespace std;
@@ -37,6 +38,8 @@ private:
bool quit = false;
} gameState;
const unique_ptr<Sound> sound;
public:
Game( );

View File

@@ -2,7 +2,9 @@
#include <iostream>
GameBoard::GameBoard( )
: lockedTetrominos(20, vector<int>(10, 0)), lockedColors(20, std::vector<SDL_Color>(10, { 0, 0, 0, 255 })), score(0), level(0), lines(0), collision(false) {
: lockedTetrominos(20, vector<int>(10, 0)),
lockedColors(20, std::vector<SDL_Color>(10, { 0, 0, 0, 255 })), score(0), level(0), lines(0), collision(false),
sound(make_unique<Sound>( )) {
spawnNewTetromino( );
}
@@ -16,20 +18,15 @@ bool GameBoard::tryMoveCurrentTetromino(int dx, int dy) {
return true;
}
void GameBoard::tryRotateCurrentTetromino( ) {
if (!currentTetromino) return;
bool GameBoard::tryRotateCurrentTetromino( ) {
if (!currentTetromino) return false;
currentTetromino->rotate(*this);
if (checkCollision(*currentTetromino))
if (checkCollision(*currentTetromino)) {
for (int i = 0; i < 3; i++)
currentTetromino->rotate(*this);
else {
Mix_Chunk* rotateSound = Mix_LoadWAV("assets/sound_effects/rotate_piece.wav");
if (rotateSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, rotateSound, 0);
}
return false;
}
return true;
}
bool GameBoard::checkCollision(const Tetromino& tetromino) const {
@@ -108,12 +105,7 @@ void GameBoard::lockTetromino( ) {
}
}
Mix_Chunk* pieceLanded = Mix_LoadWAV("assets/sound_effects/piece_landed.wav");
if (pieceLanded == nullptr)
SDL_Log("Failed to play sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, pieceLanded, 0);
}
sound->PlaySound(SoundName::PIECE_LANDED);
}
void GameBoard::clearLines( ) {

View File

@@ -8,6 +8,7 @@ extern "C" {
#include <memory>
#include <algorithm>
#include "Tetromino.hpp"
#include "Sound.hpp"
class GameBoard {
private:
@@ -27,13 +28,15 @@ private:
int level;
int lines;
const unique_ptr<Sound> sound;
public:
GameBoard( );
void update( );
bool tryMoveCurrentTetromino(int dx, int dy);
void tryRotateCurrentTetromino( );
bool tryRotateCurrentTetromino( );
bool isValidPosition(const vector<vector<int>>& shape, int x, int y) const;
void moveToBottom( );
bool moveToBottom( );
const bool isCollision( ) const;
const int getScore( ) const;

109
src/Sound.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "Sound.hpp"
Sound::Sound( ) {
if (!cachedSounds) {
cachedSounds = make_unique<unordered_map<SoundName, shared_ptr<Mix_Chunk>>>( );
cachedSounds->emplace(
SoundName::GAME_OVER,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/game_over.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::LINE_CLEAR,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/line_clear.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::MOVE_PIECE,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/move_piece.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::PIECE_LANDED,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/piece_landed.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::ROCKET_ENDING,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/rocket_ending.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::TETRIS_LINE_CLEAR,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/tetris_line_clear.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::LEVEL_UP,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/level_up.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::MENU,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/menu.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::PIECE_FALLING_AFTER_LINE_CLEAR,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/piece_falling_after_line_clear.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::PLAYER_SENDING_BLOCKS,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/player_sending_blocks.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
cachedSounds->emplace(
SoundName::ROTATE_PIECE,
std::shared_ptr<Mix_Chunk>(Mix_LoadWAV("assets/sound_effects/rotate_piece.wav"), [ ](Mix_Chunk* r) { Mix_FreeChunk(r); })
);
}
if (!cachedMusic) {
cachedMusic = make_unique<unordered_map<MusicName, shared_ptr<Mix_Music>>>( );
cachedMusic->emplace(
MusicName::MAIN_THEME,
shared_ptr<Mix_Music>(Mix_LoadMUS("assets/sound_tracks/bgm.mp3"), [ ](Mix_Music* r) {Mix_FreeMusic(r);})
);
}
}
bool Sound::PlaySound(SoundName soundName, int loop) {
auto it = cachedSounds->find(soundName);
if (it == cachedSounds->end( ) || !it->second) {
return false;
}
Mix_PlayChannel(-1, it->second.get( ), loop);
return true;
}
bool Sound::PlayMusic(MusicName musicName, int loop) {
auto it = cachedMusic->find(musicName);
if (it == cachedMusic->end( ) || !it->second) {
return false;
}
Mix_PlayMusic(it->second.get( ), loop);
return true;
}
bool Sound::PauseMusic( ) {
if (Mix_PlayingMusic( ) != 0)
Mix_PauseMusic( );
}
bool Sound::ResumeMusic( ) {
if (Mix_PausedMusic( ) == 0)
Mix_ResumeMusic( );
}
bool Sound::IncreaseVolume( ) {
int currentVolume = Mix_Volume(-1, -1);
if (currentVolume < MIX_MAX_VOLUME) {
Mix_Volume(-1, currentVolume + 2);
return true;
}
return false;
}
bool Sound::DecreaseVolume( ) {
int currentVolume = Mix_Volume(-1, -1);
if (currentVolume > 0) {
Mix_Volume(-1, currentVolume - 2);
return true;
}
return false;
}

46
src/Sound.hpp Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include <unordered_map>
#include <memory>
#include <string>
extern "C" {
#include <SDL2/SDL_mixer.h>
}
enum class SoundName {
GAME_OVER,
LINE_CLEAR,
MOVE_PIECE,
PIECE_LANDED,
ROCKET_ENDING,
TETRIS_LINE_CLEAR,
LEVEL_UP,
MENU,
PIECE_FALLING_AFTER_LINE_CLEAR,
PLAYER_SENDING_BLOCKS,
ROTATE_PIECE
};
enum class MusicName {
MAIN_THEME
};
using namespace std;
class Sound {
private:
static unique_ptr <unordered_map<SoundName, shared_ptr<Mix_Chunk>>> cachedSounds;
static unique_ptr <unordered_map<MusicName, shared_ptr<Mix_Music>>> cachedMusic;
public:
Sound( );
bool PlaySound(SoundName soundName, int loop = 0);
bool PlayMusic(MusicName musicName, int loop = -1);
bool PauseMusic( );
bool ResumeMusic( );
bool IncreaseVolume( );
bool DecreaseVolume( );
};