0
0
mirror of https://github.com/Nimac0/SDL_Minigame synced 2026-01-12 22:23:43 +00:00

Compare commits

...

10 Commits

Author SHA1 Message Date
ines
6d6c5417e2
Merge 247d6cc173536c8d27c0bd75f3a72ce83e22133f into a8e046ce073efd1bc8cbd016f4ac3c3c0176ce4e 2024-06-24 18:53:33 +00:00
a8e046ce07 #58 added exception for missing game implementation 2024-06-24 18:27:04 +02:00
ineslelin
247d6cc173 removed stray music test in GameInternal.cpp 2024-06-18 19:39:51 +02:00
ineslelin
c4c8be5829 Merge remote-tracking branch 'origin/separation-refactor' into ref/sound 2024-06-18 19:23:07 +02:00
ineslelin
b321051ac5 added channels to sound 2024-06-16 19:37:07 +02:00
ineslelin
cb1b5af358 finished sound
- implemented fade in + fade out
- implemented pause for sound + music
- implemented unpausing/restarting sound + music
2024-06-16 19:20:39 +02:00
ineslelin
6373afe3a2 working volume control 2024-05-27 12:40:51 +02:00
ineslelin
70c4d3c030 added ability to play music 2024-05-27 12:04:09 +02:00
ineslelin
db44d4d619 updated SoundManager
- created constexpr for the options to play a sound once or loop it infinitely
- removed SoundTypes enum, changed playSound() to accept a string and a bool => allows for playSound() to be used more universally
2024-05-27 11:36:02 +02:00
ineslelin
cb01c54968 updated SoundManager
- loading music from sound file now possible
- looping sound effects is possible now
2024-05-26 19:06:52 +02:00
9 changed files with 162 additions and 24 deletions

Binary file not shown.

View File

@ -36,12 +36,16 @@ public:
// sound management // sound management
void addSoundEffect(std::string id, const char* path); void addSoundEffect(std::string id, const char* path);
void addMusic(std::string id, const char* path);
SDL_Texture* getTexture(std::string id); SDL_Texture* getTexture(std::string id);
Mix_Chunk* getSound(std::string id); Mix_Chunk* getSound(std::string id);
Mix_Music* getMusic(std::string id);
private: private:
Manager* man; Manager* man;
std::map<std::string, SDL_Texture*> textures; std::map<std::string, SDL_Texture*> textures;
std::map<std::string, Mix_Chunk*> soundEffects; std::map<std::string, Mix_Chunk*> soundEffects;
std::map<std::string, Mix_Music*> music;
}; };

View File

@ -24,3 +24,8 @@ constexpr int MAP_SIZE_Y = 20;
constexpr int SPAWN_ATTEMPTS = 20; constexpr int SPAWN_ATTEMPTS = 20;
constexpr int PLAY_LOOPED = -1;
constexpr int PLAY_ONCE = 0;
constexpr int MAX_VOLUME = 128;

View File

@ -5,6 +5,7 @@
#include <map> #include <map>
#include <functional> #include <functional>
#include <string> #include <string>
#include <stdexcept>
#include "Game.h" #include "Game.h"
@ -36,8 +37,10 @@ public:
} }
Game* create(GameInternal* gameInternal) { Game* create(GameInternal* gameInternal) {
if (this->creatorFunc == nullptr) if (this->creatorFunc == nullptr) {
throw std::runtime_error("No game implementation registered!");
return nullptr; return nullptr;
}
Game* game = (this->creatorFunc)(); Game* game = (this->creatorFunc)();
game->gameInternal = gameInternal; game->gameInternal = gameInternal;
return game; return game;

View File

@ -7,13 +7,22 @@
#include "ECS.h" #include "ECS.h"
#include "TextureManager.h" #include "TextureManager.h"
enum SoundTypes // enum SoundTypes
{ // {
STEPS, // STEPS,
THROW_EGG, // THROW_EGG,
}; // };
// class Game;
class GameInternal; class GameInternal;
/*!
*
* \brief Handles music and sound.
* \details SoundManager handles loading in music and sound effects from files, playing music and sound effects and toggling the audio volume.
*
*/
class SoundManager class SoundManager
{ {
public: public:
@ -22,14 +31,40 @@ class SoundManager
for (auto& it : this->sound_cache) { for (auto& it : this->sound_cache) {
Mix_FreeChunk(it.second); Mix_FreeChunk(it.second);
} }
for (auto& it : this->music_cache) {
Mix_FreeMusic(it.second);
}
} }
SoundManager(SoundManager const&) = delete; SoundManager(SoundManager const&) = delete;
void operator=(SoundManager const&) = delete; void operator=(SoundManager const&) = delete;
std::map<const char*, Mix_Music*> music_cache;
std::map<const char*, Mix_Chunk*> sound_cache; std::map<const char*, Mix_Chunk*> sound_cache;
Mix_Chunk* loadSound(const char* fileName); Mix_Music* loadMusic(const char* fileName); //!< Loads music from a file (mp3)
static void playSound(GameInternal* game, SoundTypes sound); //! \returns a pointer to Mix_Music, which is added to a map in the AssetManager
//! \sa AssetManager::AddMusic(std::string id, const char* path)
Mix_Chunk* loadSound(const char* fileName); //!< Loads sound effects from a file (wav)
//! \returns a pointer to Mix_Chunk, which is added to a map in the AssetManager
//! \sa AssetManager::AddSound(std::string id, const char* path)
static void playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel); //!< Plays sound effects
//! handles if sounds can overlap, how often they can loop, as well as the volume at which the specified sound effect should play
static void playMusic(GameInternal* game, std::string sound, int loops, int volume, int ms); //<! Plays music
//! handles how often the track should loop, as well as the volume at which the specified track should play
static void setSoundVolume(int volume, int channel); //!< Volume handling for the entire program
static void setMusicVolume(int volume);
static void pauseSound(int channel);
static void pauseMusic();
static void restartSound(int channel);
static void restartMusic();
static void fadeOutMusic(int ms);
private: private:
}; };

View File

@ -28,6 +28,11 @@ void AssetManager::addSoundEffect(std::string id, const char* path)
soundEffects.emplace(id, this->man->getGame()->soundManager->loadSound(path)); soundEffects.emplace(id, this->man->getGame()->soundManager->loadSound(path));
} }
void AssetManager::addMusic(std::string id, const char* path)
{
music.emplace(id, this->man->getGame()->soundManager->loadMusic(path));
}
SDL_Texture* AssetManager::getTexture(std::string id) { SDL_Texture* AssetManager::getTexture(std::string id) {
return textures.at(id); return textures.at(id);
} }
@ -36,6 +41,11 @@ Mix_Chunk* AssetManager::getSound(std::string id) {
return soundEffects.at(id); return soundEffects.at(id);
} }
Mix_Music* AssetManager::getMusic(std::string id)
{
return music.at(id);
}
void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity::TeamLabel teamLabel) { void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity::TeamLabel teamLabel) {
auto& projectile(man->addEntity()); auto& projectile(man->addEntity());

View File

@ -155,6 +155,9 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he
assets->addSoundEffect("throw_egg", "assets/sound/throw_egg.wav"); assets->addSoundEffect("throw_egg", "assets/sound/throw_egg.wav");
assets->addSoundEffect("steps", "assets/sound/steps.wav"); assets->addSoundEffect("steps", "assets/sound/steps.wav");
// loading music
// assets->addMusic("background_music", "assets/sound/background_music.mp3");
//ecs implementation //ecs implementation
// player1.setTeam(Entity::TeamLabel::BLUE); // player1.setTeam(Entity::TeamLabel::BLUE);

View File

@ -14,7 +14,7 @@ void ProjectileComponent::init()
{ {
transformComponent = &entity->getComponent<TransformComponent>(); transformComponent = &entity->getComponent<TransformComponent>();
transformComponent->direction = direction; transformComponent->direction = direction;
SoundManager::playSound(this->entity->getManager().getGame(), THROW_EGG); SoundManager::playSound(this->entity->getManager().getGame(), "throw_egg", true, PLAY_ONCE, MAX_VOLUME, -1);
} }
void ProjectileComponent::update() void ProjectileComponent::update()

View File

@ -7,6 +7,26 @@
#include "GameInternal.h" #include "GameInternal.h"
#include "AssetManager.h" #include "AssetManager.h"
Mix_Music* SoundManager::loadMusic(const char* fileName)
{
auto it = this->music_cache.find(fileName);
if (it != this->music_cache.end()) {
return it->second;
}
auto music = Mix_LoadMUS(fileName);
if (music == NULL)
throw std::runtime_error(std::string("Couldn't load music '") + fileName + "'");
this->music_cache.emplace(fileName, music);
printf("Loaded music at '%s'\n", fileName);
return music;
}
Mix_Chunk* SoundManager::loadSound(const char* fileName) Mix_Chunk* SoundManager::loadSound(const char* fileName)
{ {
auto it = this->sound_cache.find(fileName); auto it = this->sound_cache.find(fileName);
@ -27,24 +47,82 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName)
return sound; return sound;
} }
void SoundManager::playSound(GameInternal* game, SoundTypes sound) // TODO: using a string here is probably... a less than stellar method, figure out how to change this
void SoundManager::playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel)
{ {
switch (sound) if(!canOverlap)
{ {
case SoundTypes::STEPS: if (Mix_Playing(channel) != 0)
if (Mix_Playing(-1) != 0) return;
break; }
if (Mix_PlayChannel(-1, game->assets->getSound("steps"), 0) == -1) { if(Mix_VolumeChunk(game->assets->getSound(sound), volume) == -1)
std::cerr << "Error playing sound 'steps': " << Mix_GetError() << std::endl; {
} std::cerr << "Error adjusting volume: " << Mix_GetError() << std::endl;
}
break; if (Mix_PlayChannel(channel, game->assets->getSound(sound), loops) == -1)
{
case SoundTypes::THROW_EGG: std::cerr << "Error playing sound '" << sound << "': " << Mix_GetError() << std::endl;
if (Mix_PlayChannel(-1, game->assets->getSound("throw_egg"), 0) == -1) {
std::cerr << "Error playing sound 'throw_egg': " << Mix_GetError() << std::endl;
}
break;
} }
} }
void SoundManager::playMusic(GameInternal* game, std::string music, int loops, int volume, int ms)
{
if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN)
return;
if(ms > 0)
{
Mix_FadeInMusic(game->assets->getMusic(music), loops, ms);
return;
}
if(Mix_VolumeMusic(volume) == -1)
{
std::cerr << "Error adjusting volume: " << Mix_GetError() << std::endl;
}
if (Mix_PlayMusic(game->assets->getMusic(music), loops) == -1)
{
std::cerr << "Error playing music '" << music << "': " << Mix_GetError() << std::endl;
}
}
void SoundManager::setSoundVolume(int volume, int channel)
{
Mix_Volume(channel, volume);
}
void SoundManager::setMusicVolume(int volume)
{
Mix_VolumeMusic(volume);
}
void SoundManager::pauseSound(int channel)
{
Mix_Pause(channel);
}
void SoundManager::pauseMusic()
{
Mix_PauseMusic();
}
void SoundManager::restartSound(int channel)
{
Mix_Resume(channel);
}
void SoundManager::restartMusic()
{
Mix_ResumeMusic();
}
void SoundManager::fadeOutMusic(int ms)
{
if(Mix_Fading() == Mix_Fading::MIX_FADING_OUT)
return;
Mix_FadeOutMusic(ms);
}