I also found that if you create CCSpirteFrame first, then use CCSprite::setDisplayFrame, blend mode cannot work; In CCAnimate’s implementation code, it use setDisplayFrame to change the texture of the CCSprite. but I don’t know why using setDisplayFrame makes blend mode not work
I believe the problem lies indeed with CCSprite::setDisplayFrame. More specifically with CCSprite::setTexture, which is called by setDisplayFrame. At the end of setTexture, this code is called:
void CCSprite::updateBlendFunc(void)
{
CCAssert (! m_pobBatchNode, "CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteBatchNode");
// it is possible to have an untextured sprite
if (! m_pobTexture || ! m_pobTexture->hasPremultipliedAlpha())
{
m_sBlendFunc.src = GL_SRC_ALPHA;
m_sBlendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
setOpacityModifyRGB(false);
}
else
{
m_sBlendFunc.src = CC_BLEND_SRC;
m_sBlendFunc.dst = CC_BLEND_DST;
setOpacityModifyRGB(true);
}
}
As you can see, the previous blend mode will always be ignored in favor of those. I’ve tried commenting out the call to updateBlendFunc() with no luck, but now that I pasted it here, I realized it was because my sprites are using a spriteBatchNode, silly me. If you’re not using a batch node, maybe fiddling with this part of the code might work.
I’ll investigate about how this works with a batch node and I’ll report back if I find something out. Any light on this that could be shed by someone else would be greatly appreciated though
@vexille thx for ur reply , u are exactly right:;ok . i find another way to solve this problem, modify the source code from CCAnimate::update( i don’t know whether is there any side effect to do this:;qst ):
void CCAnimate::update(float t)
{
// if t==1, ignore. Animation should finish with t==1
if( t < 1.0f ) {
t *= m_pAnimation->getLoops();
// new loop? If so, reset frame counter
unsigned int loopNumber = (unsigned int)t;
if( loopNumber > m_uExecutedLoops ) {
m_nNextFrame = 0;
m_uExecutedLoops++;
}
// new t for animations
t = fmodf(t, 1.0f);
}
CCArray* frames = m_pAnimation->getFrames();
unsigned int numberOfFrames = frames->count();
CCSpriteFrame *frameToDisplay = NULL;
for( unsigned int i=m_nNextFrame; i < numberOfFrames; i++ ) {
float splitTime = m_pSplitTimes->at(i);
if( splitTime <= t ) {
// notice!!
ccBlendFunc ccBldFunc = ((CCSprite*)m_pTarget)->getBlendFunc(); // i add this line, be fore setDisplayFrame, we get old BlendFunc
CCAnimationFrame* frame = (CCAnimationFrame*)frames->objectAtIndex(i);
frameToDisplay = frame->getSpriteFrame();
((CCSprite*)m_pTarget)->setDisplayFrame(frameToDisplay);
// notice!!
((CCSprite*)m_pTarget)->setBlendFunc( ccBldFunc ); // i add this line, afther setDisplayFrame, old BlendFunc is set back
CCDictionary* dict = frame->getUserInfo();
if( dict )
{
//TODO: [[NSNotificationCenter defaultCenter] postNotificationName:CCAnimationFrameDisplayedNotification object:target_ userInfo:dict];
}
m_nNextFrame = i+1;
}
// Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS
else {
break;
}
}
}