这个是向日葵的贴图,由于只找到了这样的资源图片,也就这样用了,不过这样做好处还是有的。使用遮罩让这两个向日葵只显示一个,当处于正常动画时显示上方的图片,当要生成太阳时就显示下方的图片。(同双生向日葵)
至于遮罩,则如图所示,只是显示一部分,不过需要注意的是,设置遮罩后还需要设置回默认遮罩。
有一个帖子
http://blog.csdn.net/wei_hehe/article/details/38057649
接下来看看实现吧
class SunFlower : public Plant
{
public:enum class State{Normal,ProducingSun,};
protected:State m_curState;//当前状态float m_elapsed;//当前流逝时间float m_produceSunDuration;//产出阳光 持续时间
public:SunFlower();~SunFlower();static SunFlower*create(const string&plantName);bool init(const string&plantName);virtual void update(float dt);virtual void visit();
protected:virtual void productSun();//产生太阳回调函数
};
//---------------------------------TwinSunflower------------------
class TwinSunflower : public SunFlower
{
public:TwinSunflower();~TwinSunflower();static TwinSunflower*create(const string&plantName);bool init(const string&plantName);
protected:virtual void productSun();
};
向日葵和双生向日葵非常相似,只不过向日葵一次产生一个太阳,而双生向日葵一次产生两个太阳,所以让双生向日葵继承自向日葵
bool SunFlower::init(const string&plantName)
{m_plantName = plantName;//设置正常动画auto animationName = plantName;auto animation = AnimationCache::getInstance()->getAnimation(animationName);//设置贴图auto firstFrame = animation->getFrames().front()->getSpriteFrame();m_pSprite = Sprite::createWithSpriteFrame(firstFrame);//设置位置auto size = m_pSprite->getContentSize();size.height /= 2.f;m_pSprite->setPosition(Point::ZERO);m_pSprite->setAnchorPoint(Point::ZERO);this->setContentSize(size);this->addChild(m_pSprite);//设置运行动画Animate*animate = Animate::create(animation);this->getSprite()->runAction(animate);m_produceSunDuration = 2.f;return true;
}
注意这个init函数,是需要一个字符串的,这样是为了避免硬编码,虽然知道这个是向日葵。
然后获取Animation,之后再设置贴图,然后设置内部的精灵位置和锚点,并且运行正常动画
还有一个就是m_produceSunDuration,这个是产生太阳动画的持续时间。
void SunFlower::update(float dt)
{//当前处于正常状态if (m_curState == State::Normal){m_elapsed += dt;//切换状态if (m_elapsed >= this->getColdDownTime() - m_produceSunDuration){m_elapsed = 0.f;m_curState = State::ProducingSun;//改变内部精灵位置auto pos = m_pSprite->getPosition();auto size = this->getContentSize();m_pSprite->setPosition(pos - Point(0.f,size.height));}}else if (m_curState == State::ProducingSun){m_elapsed += dt;//在1s后产生太阳if (m_elapsed >= m_produceSunDuration){this->productSun();m_elapsed = 0.f;m_curState = State::Normal;//改变内部精灵位置auto pos = m_pSprite->getPosition();auto size = this->getContentSize();m_pSprite->setPosition(pos + Point(0.f,size.height));}}
}
至于遮罩则是重写visit即可,但由于我使用的是SDL,所以会和cocos2dx不同,下面代码供参考
void SunFlower::visit()
{auto size = this->getContentSize();auto pos = this->getWorldPosition();SDL_Rect rect = {int(pos.x),int(pos.y),(int)size.width,(int)size.height};Director::getInstance()->getRenderer()->renderSetClipRect(&rect);Node::visit();Director::getInstance()->getRenderer()->renderSetClipRect(nullptr);
}
然后就是产生阳光方法
void SunFlower::productSun()
{//设置一个动作Size size = this->getContentSize(); auto x = RANDOM(0.f,size.width);auto y = RANDOM(0.f,size.height);JumpBy*jump = JumpBy::create(0.8f,Point(x,y),-size.height,1);auto pos = this->getPosition();auto realPos = this->getParent()->convertToWorldSpace(pos);m_pDelegate->makeSun(25,jump,realPos);
}
双生向日葵内部回调的也是这个,只不过循环两次
void TwinSunflower::productSun()
{//调用两次for (auto i = 0;i < 2;i++){SunFlower::productSun();}
}
然后就是植物层有一个产生植物方法
Plant*PlantLayer::makePlant(const string&name)
{Plant*plant = nullptr;if (name == SUNFLOWER_NAME){plant = m_pPlantFactory->createSunFlower(name);}else if (name == TWINSUNFLOWER_NAME){plant = m_pPlantFactory->createTwinSunflower(name);}if (plant != nullptr){m_plants.push_back(plant);}return plant;
}
然后就是植物工厂的实现
SunFlower*PlantFactory::createSunFlower(const string&plantName)
{SunFlower*plant = SunFlower::create(plantName);//设置属性plant->setCollisionType(CollisionType::Plant);plant->setColdDownTime(24.f);plant->setHitPoint(300);//初始化刚体plant->initBody();plant->addFixturesToBody(plantName);return plant;
}TwinSunflower*PlantFactory::createTwinSunflower(const string&plantName)
{TwinSunflower*plant = TwinSunflower::create(plantName);//设置属性plant->setCollisionType(CollisionType::Plant);plant->setColdDownTime(24.f);plant->setHitPoint(300);//初始化刚体plant->initBody();plant->addFixturesToBody(plantName);return plant;
}
创建植物,设置属性,设置冷却时间,设置血量,之后再初始化刚体
bool GameScene::tryPlanting(Card*card,Terrain*terrain)
{bool bRet = false;auto topPlant = terrain->getTopPlant();//获取必要物品auto necessaryItem = card->getNecessoryItem();//升级植物if (!necessaryItem.empty() && topPlant != nullptr&& topPlant->getPlantName() == necessaryItem){//创建新植物auto newPlant = m_pPlantLayer->makePlant(card->getCardName());newPlant->setActiveTime(card->getActiveTime());newPlant->setPosition(terrain->getPosition());newPlant->setDelegate(this);//添加到entity layer 场景auto entityLayer = this->getEntityLayer();entityLayer->addChild(newPlant);terrain->setInnerPlant(newPlant);//移除旧植物m_pPlantLayer->removePlant(topPlant);topPlant->removeFromParent();bRet = true;}//...
这里实现了植物的升级。
如图,后面则是box2d的调试绘图