//----------------------------------------------------------------------- size_t ParticleSystem::_updateTechniques(Real timeElapsed) { /** Update all techniques if particle system is started (only if the techniques aren't emitted themselves) and return the total number of emitted particles. Note, that emitted techniques are updated by the technique that is responsible for emitting them. The technique that is emitting pooled techniques is also responsible to take the (world)AABB of that pooled technique into account. */ /** V 1.4: Bug http://www.fxpression.com/phpBB3/viewtopic.php?f=5&t=438&p=1453#p1453 For some reason particle nodes get updated before the 'make particle local' call in the particle technique, and others do not. Some kind of timing issue. Explicitly calling Node::_update here fixes the problem Note, the patch in the link was to put the code in each technique. It seems more obvious to put it in the particle system itself, so it is updated only once. */ if (isInScene() && getParentNode()) { getParentNode()->_update(true, true); } ParticleTechniqueIterator it; ParticleTechniqueIterator itEnd = mTechniques.end(); size_t particlesLeft = 0; bool mAABBUpdate = mParentNode && (mBoundsAutoUpdate || mBoundsUpdateTime > 0.0f); bool merge = mAABBUpdate; AxisAlignedBox worldAABB(mParentNode->_getDerivedPosition(), mParentNode->_getDerivedPosition()); for (it = mTechniques.begin(); it != itEnd; ++it) { if (!(*it)->_isMarkedForEmission()) { // Only call this if update bounds is needed. if (merge) { // Call _notifyUpdateBounds() for each Particle Technique, so the mWorldAABB in the // ParticleTechnique::_update() function is (re)calculated. (*it)->_notifyUpdateBounds(); } // Always update the ParticleTechniques (*it)->_update(timeElapsed); // Merge worldAABB's of all ParticleTechniques if (merge) { // Get the WorldAABB from each technique and merge it with the worldAABB. worldAABB.merge((*it)->getWorldBoundingBox()); // If worldAABB is infinite, ignore the other Particle Techniques. if (worldAABB.isInfinite()) { merge = false; } } // Count all left particles, used for anyone who needs it. particlesLeft += (*it)->getNumberOfEmittedParticles(); } } if (mState == ParticleSystem::PSS_STOPPED) { /** Don't bother to update the mAABB, because the system is stopped in one of the techniques. The bounds must be reset, because even though the stop() has been called (which alread resets the bounds) another technique in the list might set the bounds again. */ _resetBounds(); } else if (mAABBUpdate) { // If needed, update mAABB if (!worldAABB.isNull()) { if (mTightBoundingBox) { // Wrap the bounding box tight around the particle system mAABB = worldAABB; mAABB.transformAffine(mParentNode->_getFullTransform().inverseAffine()); } else { // Merge with the current bounding box // Note, that the mAABB must in localspace, so transformation of the worldAABB is required. AxisAlignedBox newAABB(worldAABB); newAABB.transformAffine(mParentNode->_getFullTransform().inverseAffine()); // Merge calculated box with current AABB. mAABB.merge(newAABB); } // Update bounding radius Real sqDist = std::max(mAABB.getMinimum().squaredLength(), mAABB.getMaximum().squaredLength()); mBoundingRadius = Math::Sqrt(sqDist); } else { _resetBounds(); } // V1.4 Remove this part, because the node is updated each frame. // Notify the parent node that the bounds are changed // mParentNode->needUpdate(); } return particlesLeft; }
void GameScene::addTouchListener() { auto touchListener = EventListenerTouchOneByOne::create(); touchListener->onTouchBegan = [this](Touch* t,Event* e)->bool{ auto menuCoo = menu->convertToNodeSpace(t->getLocation()); Rect oldAABB = buttonCoco->getBoundingBox(); Vec2 oldVec = oldAABB.origin; Vec2 newVec = oldVec-buttonCoco->getContentSize()/2; Rect newAABB(newVec.x,newVec.y,oldAABB.size.width,oldAABB.size.height); if(mpProgressTimer->getPercentage()==100.0f&&newAABB.containsPoint(menuCoo)){ isMagic = true; coco->playAnimation(BaseSprite::State::magic); if(!eff){ eff = EffSprite::create("pfca/effect/eff_point_Coco_ult.fca", "effect/eff_point_Coco_ult"); this->addChild(eff); } eff->setVisible(true); eff->setPosition(0-_director->getWinSize().width/2,0); eff->playAnimation(BaseSprite::State::magic,CallFunc::create(CC_CALLBACK_0(GameScene::effectCallback, this))); mpProgressTimer->setPercentage(0.f); } return true; }; auto hurtLisener = EventListenerCustom::create("hurt", [this](EventCustom* e)->void{ auto hurtObject = (BaseSprite*)e->getUserData(); Label* l = nullptr; ProgressTimer* hp = nullptr; if(hurtObject==boss){ l = l1; hp = effectHpProgressTimer[0]; }else{ l = l2; hp = effectHpProgressTimer[1]; } if(dynamic_cast<TreeBoss*>(hurtObject)){ l->setPosition(hurtObject->getPosition()+Vec2(_director->getWinSize().width/2,_director->getWinSize().height/2+200)); hp->setPosition(hurtObject->getPosition()+Vec2(_director->getWinSize().width/2,_director->getWinSize().height/2+180)); } else{ l->setPosition(hurtObject->getPosition()+Vec2(_director->getWinSize().width/2,_director->getWinSize().height/2+100)); hp->setPosition(hurtObject->getPosition()+Vec2(_director->getWinSize().width/2,_director->getWinSize().height/2+130)); } hp->setPercentage((hurtObject->getProperty().curLife/hurtObject->getProperty().maxLife)*100); l->setString("-"+Value((int)hurtObject->getCurHurt()).asString()); if(!l->getParent()){ this->addChild(l,3); } if(!hp->getParent()){ this->addChild(hp,3); } hp->setVisible(true); if(!l->isVisible()){ l->setVisible(true); l->setOpacity(255); } auto move = MoveBy::create(0.5f, Vec2(0,20)); auto fade = FadeOut::create(0.5f); l->runAction(Sequence::create(move, fade,CallFunc::create(std::bind(&GameScene::lableCallback, this,l)),nullptr)); hp->runAction(Sequence::create(DelayTime::create(1.0f),CallFuncN::create([](Node* n){ n->setVisible(false); }), NULL)); }); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener,buttonCoco); _eventDispatcher->addEventListenerWithSceneGraphPriority(hurtLisener,this); }