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

removed maps regarding music and sound effects from the AssetManager

reworked SoundManager to use enum classes as keys in its maps and to no longer use the AssetManager
added possibility to set sound effect of projectiles when creating them (was hard coded)
This commit is contained in:
freezarite 2025-01-28 19:08:05 +01:00
parent 361687f09f
commit 9bb9d0fbcc
8 changed files with 106 additions and 58 deletions

View File

@ -6,6 +6,7 @@
#include <functional>
#include "Entity.h"
#include "SoundEffects.h"
class Vector2D;
class Manager;
@ -24,24 +25,14 @@ public:
AssetManager(Manager* manager);
~AssetManager();
void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, float speed, Textures textureEnum, Entity* owner);
void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, float speed, Textures textureEnum, Entity* owner, SoundEffects soundEffect);
void createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture);
Vector2D calculateSpawnPosition();
PowerupType calculateType();
// sound management
void addSoundEffect(std::string id, const char* path);
void addMusic(std::string id, const char* path);
Mix_Chunk* getSound(std::string id);
Mix_Music* getMusic(std::string id);
private:
Manager* man;
std::map<std::string, Mix_Chunk*> soundEffects;
std::map<std::string, Mix_Music*> music;
};

View File

@ -0,0 +1,3 @@
#pragma once
enum class BackgroundMusic;

View File

@ -3,6 +3,7 @@
#include "Component.h"
#include "Vector2D.h"
#include "Constants.h"
#include "SoundEffects.h"
class TransformComponent;
@ -11,8 +12,8 @@ class ProjectileComponent : public Component
//can maybe be split in separate .cpp file
public:
ProjectileComponent(int range, int speed, Vector2D direction, Entity* owner)
: range(range), speed(speed), direction(direction), owner(owner) {}
ProjectileComponent(int range, int speed, Vector2D direction, Entity* owner, SoundEffects soundEffect)
: range(range), speed(speed), direction(direction), owner(owner), soundEffect(soundEffect) {}
~ProjectileComponent() {}
void init() override;
@ -28,4 +29,6 @@ private:
Entity* owner = nullptr;
Vector2D direction;
SoundEffects soundEffect;
};

3
include/SoundEffects.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
enum class SoundEffects;

View File

@ -6,6 +6,8 @@
#include "ECS.h"
#include "TextureManager.h"
#include "BackgroundMusic.h"
#include "SoundEffects.h"
class GameInternal;
@ -17,8 +19,12 @@ class GameInternal;
*/
class SoundManager
{
public:
SoundManager() {}
SoundManager() {
this_instance = this;
}
~SoundManager() {
for (auto& it : this->sound_cache) {
Mix_FreeChunk(it.second);
@ -32,35 +38,32 @@ class SoundManager
SoundManager(SoundManager const&) = delete;
void operator=(SoundManager const&) = delete;
std::map<const char*, Mix_Music*> music_cache;
std::map<const char*, Mix_Chunk*> sound_cache;
/*!
/*
* \brief Loads music from a file (mp3)
* \returns a pointer to Mix_Music
* \sa AssetManager::AddMusic(std::string id, const char* path)
*/
Mix_Music* loadMusic(const char* fileName);
/*!
* \brief Loads sound effects from a file (wav)
* \returns a pointer to Mix_Chunk
* \sa AssetManager::AddSound(std::string id, const char* path)
*/
Mix_Chunk* loadSound(const char* fileName);
Mix_Chunk* loadSound(const char* fileName);
*/
/*!
* \brief Handles playing of 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
* and on which channel the soundeffect should play.
*/
static void playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel);
static void playSound(SoundEffects sound, bool canOverlap, int loops, int volume, int channel);
/*!
* \brief Handles playing of music
*
* Handles how often track can loop, as well as the volume at which the specified track should play and if it fades in.
*/
static void playMusic(GameInternal* game, std::string sound, int loops, int volume, int ms);
static void playMusic(BackgroundMusic sound, int loops, int volume, int ms);
static void setSoundVolume(int volume, int channel); //!< Volume handling for sound effects (either all or on a specific channel)
static void setMusicVolume(int volume); //!< Volume handling for music track
@ -73,5 +76,15 @@ class SoundManager
static void fadeOutMusic(int ms); //!< Handles fading out a music track
static void addSingleSoundEffect(SoundEffects soundEffect, const char* path);
static void addSoundEffects(const std::map<SoundEffects, const char*> &effects);
static void addSingleBackgroundMusic(BackgroundMusic backgroundMusic, const char* path);
static void addBackgroundMusic(const std::map<BackgroundMusic, const char*> &backgroundMusic);
private:
std::map<BackgroundMusic, Mix_Music*> music_cache;
std::map<SoundEffects, Mix_Chunk*> sound_cache;
static SoundManager* this_instance;
};

View File

@ -22,32 +22,13 @@ AssetManager::AssetManager(Manager* manager) : man(manager) {}
AssetManager::~AssetManager() {}
void AssetManager::addSoundEffect(std::string id, const char* 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));
}
Mix_Chunk* AssetManager::getSound(std::string 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, float speed, Textures textureEnum, Entity* owner) {
void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, float speed, Textures textureEnum, Entity* owner, SoundEffects soundEffect) {
auto& projectile(man->addEntity());
projectile.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects
projectile.addComponent<SpriteComponent>(textureEnum, 4);
projectile.addComponent<ProjectileComponent>(range, speed, velocity, owner);
projectile.addComponent<ProjectileComponent>(range, speed, velocity, owner, soundEffect);
projectile.addComponent<ColliderComponent>("projectile", 0.6f);
projectile.addGroup((size_t)Entity::GroupLabel::PROJECTILE);
}

View File

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

View File

@ -8,9 +8,10 @@
#include "GameInternal.h"
#include "AssetManager.h"
/*
Mix_Music* SoundManager::loadMusic(const char* fileName)
{
auto it = this->music_cache.find(fileName);
//auto it = this->music_cache.find(fileName);
if (it != this->music_cache.end()) {
return it->second;
@ -48,14 +49,21 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName)
return sound;
}
void SoundManager::playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel)
*/
void SoundManager::playSound(SoundEffects sound, bool canOverlap, int loops, int volume, int channel)
{
if (!this_instance->sound_cache.contains(sound)) {
std::cerr << "Error playing Sound-Effect: sound effect not found" << std::endl;
return;
}
if(!canOverlap)
{
// dev needs to specify a channel for this check to work, if they set it to -1 and let sdl pick the first available
// channel mix_getchunk() won't work
if (Mix_Playing(channel) != 0 &&
Mix_GetChunk(channel) == game->assets->getSound(sound) &&
Mix_GetChunk(channel) == this_instance->sound_cache.at(sound) &&
channel != -1)
{
return;
@ -64,25 +72,30 @@ void SoundManager::playSound(GameInternal* game, std::string sound, bool canOver
Mix_HaltChannel(channel);
}
if(Mix_VolumeChunk(game->assets->getSound(sound), volume) == -1)
if(Mix_VolumeChunk(this_instance->sound_cache.at(sound), volume) == -1)
{
std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl;
}
if (Mix_PlayChannel(channel, game->assets->getSound(sound), loops) == -1)
if (Mix_PlayChannel(channel, this_instance->sound_cache.at(sound), loops) == -1)
{
std::cerr << "Error playing sound '" << sound << "': " << SDL_GetError() << std::endl;
std::cerr << "Error playing sound " << ": " << SDL_GetError() << std::endl;
}
}
void SoundManager::playMusic(GameInternal* game, std::string music, int loops, int volume, int ms)
void SoundManager::playMusic(BackgroundMusic music, int loops, int volume, int ms)
{
if (!this_instance->music_cache.contains(music)) {
std::cerr << "Error playing music: music not found" << std::endl;
return;
}
if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN)
return;
if(ms > 0)
{
Mix_FadeInMusic(game->assets->getMusic(music), loops, ms);
Mix_FadeInMusic(this_instance->music_cache.at(music), loops, ms);
return;
}
@ -90,11 +103,6 @@ void SoundManager::playMusic(GameInternal* game, std::string music, int loops, i
{
std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl;
}
if (Mix_PlayMusic(game->assets->getMusic(music), loops) == -1)
{
std::cerr << "Error playing music '" << music << "': " << SDL_GetError() << std::endl;
}
}
void SoundManager::setSoundVolume(int volume, int channel)
@ -134,3 +142,49 @@ void SoundManager::fadeOutMusic(int ms)
Mix_FadeOutMusic(ms);
}
void SoundManager::addSingleSoundEffect(SoundEffects soundEffect, const char *path) {
if (this_instance->sound_cache.contains(soundEffect)) {
std::cerr << "Error when adding Sound-Effect: sound-effect with that key already in cache" << std::endl;
return;
}
Mix_Chunk* sound = Mix_LoadWAV(path);
if (sound == nullptr) {
std::cerr << "Error when loading Sound-Effect: could not load sound effect from " << path << std::endl;
return;
}
this_instance->sound_cache.emplace(soundEffect, sound);
}
void SoundManager::addSingleBackgroundMusic(BackgroundMusic backgroundMusic, const char *path) {
if (this_instance->music_cache.contains(backgroundMusic)) {
std::cerr << "Error when adding Sound-Effect: sound-effect with that key already in cache" << std::endl;
return;
}
Mix_Music* music = Mix_LoadMUS(path);
if (music == nullptr) {
std::cerr << "Error when loading Sound-Effect: could not load sound effect from " << path << std::endl;
return;
}
this_instance->music_cache.emplace(backgroundMusic, music);
}
void SoundManager::addSoundEffects(const std::map<SoundEffects, const char *> &effects) {
for (auto effect : effects)
addSingleSoundEffect(effect.first, effect.second);
}
void SoundManager::addBackgroundMusic(const std::map<BackgroundMusic, const char *> &backgroundMusic) {
for (auto track : backgroundMusic)
addSingleBackgroundMusic(track.first, track.second);
}