My game has 50 animals, each making unique sounds. When the game starts up, 5-25 random animals will be on the screen (it will be different between each player). When player picks up an animal, the animal makes a noise.
I don’t want to preload all 50 animal sounds at the beginning of the game because the player might not need all of the sounds (if they only see 5 and then leave the game).
Right now, I have it so when the player picks up an animal, it preloads that sound and plays it. But if the player picks up the same animal 3 times in a row, it will preload the sound 3 times. Is there a way to detect if a sound has been preloaded so as not to load it again?
Or is there a better way for me to do this? Any suggestions please.
Along those lines, unloading effects would requiring knowing which sounds were loaded. I am thinking of tracking the loaded sounds in a list and then looping through it to unload in the end. Is this correct?
Maybe you could build a type to represent your data. Either a struct, or a class.
If my assumptions about cocos are wrong, and this is a needless abstraction, then ignore this:
// Struct :
// Manually set the attributes as you modify them. Keeping a list of this wouldn't be so bad.
typedef struct {
bool loaded;
std::string name;
} SoundInfo;
// Class:
// Makes more sense imo, since the data has state. Your desired behavior can be handled
// internally. Untested.
#include "SimpleAudioEngine.h"
class MySound
{
public:
MySound(const std::string newName);
~MySound();
void load();
void unload();
const bool play();
const bool getIsLoaded();
private:
bool isLoaded;
std::string name;
};
MySound::MySound(const std::string newName) : isLoaded(false), name("")
{
name = newName;
this->load();
}
MySound::~MySound() {this->unload();}
void MySound::load()
{
if (!this->isLoaded)
{
SimpleAudioEngine::sharedEngine()->preloadEffect(name.c_str());
}
}
void MySound::unload()
{
if (this->isLoaded)
{
SimpleAudioEngine::sharedEngine()->unloadEffect(name.c_str());
}
}
const bool MySound::play()
{
// You can silently fail and return an error (return false), or preload the sound and then play it (return true).
if (!isLoaded) {this->load();}
SimpleAudioEngine::sharedEngine()->playEffect(name.c_str());
return true;
}
const bool MySound::getIsLoaded() {return isLoaded;}
// Using MySound:
// Scenario: There's a dog, a cow, and a duck.
MySound dogBark("bark.wav");
MySound cowMoo("moo.wav");
MySound duckQuack("quack.wav");
// If they leave scope, they will be destroyed and unloaded automatically, until then you can play them
// with a "fire and forget" philosophy. Now you don't need their handling logic muddying up your scene logic.
// Their lifecycle is up to you.
void playerPicksUpAnimalCallback(AnimalNode* const animal)
{
const int ANIMAL_TYPE = animal->getTag();
enum {DOG, COW, DUCK, PIG, SNAKE};
switch (ANIMAL_TYPE)
{
case DOG:
dogBark.play();
break;
case COW:
cowMoo.play();
break;
case DUCK:
duckQuack.play();
break;
// etc.
};
}