Since cocos2dx’s AudioEngine doesn’t really provide any methods for delaying audio play, I’ve decided to try using actions for this purpose.
I was aiming to create a list of delayed, overlapping ambient tracks.
Used cocos2d::DelayTime actions interleaved with calls to my Play function like this:
cocos2d::Vector<cocos2d::FiniteTimeAction*> actionList;
for(unsigned int i = 0; i < _ambientBlock.size(); ++i)
{
if(_ambientBlock[i].timeOffset == 0.0f)
{
// do not push any delay before this track, starts playing immediately
}
else if(i == 0) // first element, don't need to calculate, just read value
{
actionList.pushBack(cocos2d::DelayTime::create((float)(_ambientBlock[i].timeOffset)));
}
else // calculate proper delay time, take into account previously accumulated delay
{
float precedingDelay = ((float)_ambientBlock[i].timeOffset) - ((float)_ambientBlock[i - 1].timeOffset);
actionList.pushBack(cocos2d::DelayTime::create(precedingDelay));
}
actionList.pushBack(cocos2d::CallFunc::create([i](){
PlayAmbient(_ambientBlock[i].fileName);
}));
}
cocos2d::Sequence* sequence = cocos2d::Sequence::create(actionList);
_audioEntity->runAction(sequence);
However it looks like the lambda is never called. If I put a breakpoint on
PlayAmbient(_ambientBlock[i].fileName);
It is never hit. Nothing’s being played either.
_audioEntity is just a cocos2d::Node that’s been created once at the beginning of the program and retained with CC_SAFE_RETAIN. It’s not a part of any scene.
Lambda functions are notorious for not behaving well with breakpoints. Throw in a CCLOG(); cclog(); and/or printf() to see if it is called.
Try first manual sequence without array.
Put a .5f second delay time between each play. Sequence(CallFunc, Delay, CallFunc, Delay, CallFunc ...etc .. , null);
Then put them into Vector with pushBack as you have it.
Only after that’s working try your code with some printf/cclog to check code path. Maybe _ambientBlock has size 0? Maybe _audioEntity isn’t actually running, and thus sequence is never started.
Now what does it mean for a Node to be “running”? From your answer I can figure that this state is required to be able to run any actions on the Node.
How can I make sure it is running? Does it have to be a part of a scene that’s currently running? If not, can I somehow manually change it’s state to running?
Can’t seem to find any documentation covering the subject and the only method that directly names “running” (and does not refer to actions) is the one I just called.
_audioEntity needs to be added as a child of some node that’s ‘running’, which essentially just means it needs to exist in the current Scene’s node hierarchy graph.
You can look into ActionManager and manually schedule, but easiest is to add it as a child like any other visible Sprite/Node.
Thanks, that clears up a lot, but there’s one thing I’m in doubt about. Since I intend to use this node for running audio-related sequences, it is possible that the current scene will at some point no longer be current during the action running time.
I suspect this might interfere.
Is that the case? If yes, is there any way to have the Node running independent of scenes?