cocos2dx 植物大战僵尸 6 植物层

来源:互联网 发布:网络医生兼职 编辑:程序博客网 时间:2024/06/10 02:48
上一节实现了塔基的行数的确定,这一节就着手于植物的创建。
下面就说说植物类的继承关系

这里说明下,这个游戏我打算使用box2d,不过这里并不是要进行物理模拟,而是仅仅用作物理碰撞,因为有些地方使用box2d会更好,比如,在屋顶场景中有个斜坡,豌豆等子弹碰到后会消失,使用box2d就不难实现,而且使用box2d也便于碰撞调试等等。另外,我也使用了Physics Editor和TexturePacker等软件(这两个软件都是收费的),主要是为了便于开发。
B2Entity 就是box2d entity,就是参与物理碰撞的实体。主要用于那些既参与碰撞,又显示贴图的对象。
/*主要了是为了在发生碰撞时便于类型转换*/enum class CollisionType{None,Plant,//植物类型};class B2Entity:public Entity{SDL_SYNTHESIZE(CollisionType,m_collisionType,CollisionType);protected:b2Body*m_pBody;bool m_bActive;//是否存活,如果是则存在box2d碰撞面积public:B2Entity();~B2Entity();virtual void update(float dt) = 0;/**初始化刚体*/void initBody();/**为内部的body添加b2Fixture,内部由GB2ShapeCache-x提供支持@shape 在GB2ShapeCache中 的shape所对应的形体的名称shape必须在这之前已经加载到GB2ShapeCache中,并且body不能为nullptr*/void addFixturesToBody(const std::string &shape);//清除原来body的全部fixturevoid clearFixtures();//获取当前形状b2Fixture*getFixtureList()const;void setActive(bool active);bool isActive()const;};
这里主要说明的就是CollisionType,box2d在发生碰撞时,如果需要对碰撞进行监听,就需要继承自吧b2ContactListener的类实现BegainContact和EndContact等方法,因为在box2d中碰撞的都是形状fixture,所以需要获取fixture的body,然后再根据body->GetUserData()获取刚体所对应的实体,然后再根据实体进行一些逻辑判断
B2Entity::~B2Entity(){if(m_pBody)//回收内存{auto pWorld = GameScene::getWorld();if (pWorld)pWorld->DestroyBody(m_pBody);}m_pBody = nullptr;}void B2Entity::initBody(){b2BodyDef bodyDef;bodyDef.type = b2_dynamicBody;//创建刚体b2World*pWorld = GameScene::getWorld();m_pBody = pWorld->CreateBody(&bodyDef);//设置刚体用户数据m_pBody->SetUserData(this);}void B2Entity::addFixturesToBody(const std::string &shape){GB2ShapeCache::getInstance()->addFixturesToBody(m_pBody,shape);}void B2Entity::clearFixtures(){//先清除原先的fixturefor(auto fixture = m_pBody->GetFixtureList();fixture;){auto temp = fixture;fixture = fixture->GetNext();m_pBody->DestroyFixture(temp);}}b2Fixture*B2Entity::getFixtureList()const{if(m_pBody)return m_pBody->GetFixtureList();return nullptr;}void B2Entity::setActive(bool active){if(m_pBody == nullptr)return;m_pBody->SetActive(active);m_bActive = active;}bool B2Entity::isActive()const{return m_bActive;}
在这里使用了GB2ShapeCache-x.h文件,这个是和PhysicsEditor的导出文件所对应的一个单例类,主要负责形状的创建和绑定刚体。
clearFixture()是为了便于重用。还有就是setActive无法在b2ContactListener的回调函数中进行使用,这个需要注意。

Plant则是植物类的父类,目前也没什么内容,待以后扩展使用。
class PlantDelegate{public:virtual ~PlantDelegate(){}virtual void makeSun(int number,FiniteTimeAction*action,const Point&bornPos)=0;};class Plant : public B2Entity{SDL_SYNTHESIZE(float,m_fColdDownTime,ColdDownTime);//总cdSDL_SYNTHESIZE(int,m_nHitPoint,HitPoint);//血量SDL_SYNTHESIZE(ActiveTime,m_activeTime,ActiveTime);//活动时间SDL_SYNTHESIZE(string,m_plantName,PlantName);//植物名称protected:PlantDelegate*m_pDelegate;public:Plant();~Plant();void setDelegate(PlantDelegate*delegate);virtual void update(float dt);};
Plant类中保存了一些基本的属性,还有一个就是PlantDelegate,这个使用的是委托,目前仅仅有一个makeSun方法,使用委托的好处就是解耦,这样Plant就不需要知道PlantDelegate是什么,只要它实现了对应的方法就可以了

接着就是PlantLayer植物层和PlantFactory植物工厂的实现了,植物层现在没什么内容,目前仅仅涉及了植物的逻辑更新和植物的产生,内部调用了植物工厂方法
bool PlantLayer::init(){m_pPlantFactory = PlantFactory::create();m_pPlantFactory->retain();return true;}//进行植物的逻辑更新 TODOvoid PlantLayer::update(float dt){for (auto it = m_plants.begin();it != m_plants.end();){auto plant = *it;plant->update(dt);it++;}}
另外植物工厂不是单例类,在植物层中保存了它的指针。
void GameScene::onTouchEnded(Touch*touch,SDL_Event*event){auto pos = touch->getLocation();//是否点击了ProductLayerauto product = m_pProductLayer->getClickedProduct(pos);if (product){product->setClicked(true);this->collectProduct(product);return;}auto nodePos = m_pLevelLayer->convertToNodeSpace(pos);//是否点击了某一个terrainauto terrain = m_pLevelLayer->getClickedTerrain(nodePos);//所有操作对要经过terrainif (terrain == nullptr)return;auto selectedCard = m_pCardLayer->getSelectedCard();//存在选中的卡片,则阳光足够,cd完成if (selectedCard){bool bRet = false;bRet = this->tryPlanting(selectedCard,terrain);//创建完成if (bRet){//减少阳光值this->subSun(selectedCard->getWorth());//取消点击m_pCardLayer->unselectedCard();//该卡片开始cdselectedCard->setCurCD(selectedCard->getCD());}}//是否点击了铲子 TODO}
和以前类似,只不过如果创建成功就减去阳光 取消卡片的选中,同时卡片开始cd
bool GameScene::tryPlanting(Card*card,Terrain*terrain){auto topPlant = terrain->getTopPlant();//获取必要物品auto necessaryItem = card->getNecessoryItem();//升级植物if (!necessaryItem.empty() && topPlant != nullptr&& topPlant->getPlantName() == necessaryItem){//创建新植物//移除旧植物TODO}//种植植物else if (necessaryItem.empty()){//地形上的植物为空 并且地形符合,则创建if (topPlant == nullptr && card->isIncludeTerrain(terrain->getTerrainType())){auto plant = m_pPlantLayer->makePlant(card->getCardName());//再设置一些基础属性plant->setActiveTime(card->getActiveTime());plant->setPosition(terrain->getPosition());plant->setDelegate(this);//添加到entity layer 场景auto entityLayer = this->getEntityLayer();entityLayer->addChild(plant);//设置塔基内部的植物terrain->setInnerPlant(plant);return true;}//存在植物,但如果是容器植物,则继续判断else if(topPlant != nullptr){}}return false;}
在这里进行了植物的创建,设置了一些属性,并且添加到了场景之中,其他的则是以后扩展使用的。
下一节实现向日葵
原创粉丝点击