How to schedule objects that shouldn't be displayed

Hi all!

I didn’t find a built in way to fade out the background music (Cocos2d-X 2.2.0), so I started building a simple audio manager singleton class. The idea was that this class should have a function that lower the volume by 10, and by running this over and over with a delay the music would fade out.

The problem I face is that when I try to schedule the function it is never run. The only way I could get the function scheduled is by adding my audio manager class as a child of what’s currently displayed.

Here is AudioManager.h:
<pre><code class=“cpp”>
#include “cocos2d.h”

class AudioManager : public cocos2d::CCNode
{
private:
AudioManager();
virtual bool init();

static AudioManager\* m\_mySingleton;

protected:
void fadeOutBackgroundMusicHelper(cocos2d::CCTime dt);

public:
static AudioManager* getShared();

void fadeOutBackgroundMusic();

};
</code></pre>

and AudioManager.cpp:
<pre><code class=“cpp”>
#include “AudioManager.h”
#include “SimpleAudioEngine.h”

USING_NS_CC;

AudioManager* AudioManager::m_mySingleton = NULL;

AudioManager::AudioManager() {}

AudioManager* AudioManager::getShared() {
if(NULL == m_mySingleton) {
m_mySingleton = new AudioManager();
m_mySingleton->init();
}
return m_mySingleton;
}

bool AudioManager::init() {
if(!CCNode::init()) {
return false;
}
return true;
}

void AudioManager::fadeOutBackgroundMusic() {
this->schedule(schedule_selector(AudioManager::fadeOutBackgroundMusicHelper), 0.1, 9, 0);
}

void AudioManager::fadeOutBackgroundMusicHelper(CCTime dt) {
CocosDenshion::SimpleAudioEngine *audioEngine = CocosDenshion::SimpleAudioEngine::sharedEngine();

float vol = audioEngine-\>getBackgroundMusicVolume();
CCLOG("volume: f", vol);

if(vol > 0.1) {
audioEngine~~>setBackgroundMusicVolume;
} else {
audioEngine~~>stopBackgroundMusic();
audioEngine~~>setBackgroundMusicVolume;
CCLOG (“Background music stopped”);
}
}
</pre>
The function is scheduled and the music is faded only if I add the object as a child the the current layer like this:
<pre>
AudioManager *am = AudioManager::getShared;
this~~>addChild(am);
am->fadeOutBackgroundMusic();

There must be a better way to do this! So my question is: Who can I schedule a function that is not supposed to be part of the displayed content?

Thank you in advance :slight_smile:

There is no way to make the scheduler work if the node is not a part of the scene graph. That’s how Cocos2d is designed.
I am not sure if this will work, but maybe you could try to use a custom action?

Thank you for you answer dot squid!
Can you please explain how a custom action works?

Just take a look at any built-in action. Briefly, you need to inherit CCActionInterval and implement your own ‘step’ method. Action takes a CCNode as a target and modifies its properties in ‘step’ method.

Of cause! Solved it now. A custom action was a great idea.

Thanks for your help dot squid!

Thanks for testing my idea (:
Good luck and happy coding.

am->onEnter();

Here’s a custom action class that I used: