现在,对于游戏的基本准备都已经做好,之后需要考虑的,就是游戏逻辑的处理,主要考虑一下几个方面:
1 判断方块是否已经落下停止,并下落新的方块;
2 方块落下后,判断是否符合消行条件,进行消行;
3 根据下落或者消行进行计分。
这些判断,需要定时处理,因此这里需要使用到默认更新的update。
在初始化中,需要调用:
this->scheduleUpdate();
如果需要停止更新,可以调用:
this->unscheduleUpdate();
这样,就可以在void update(float delaty)函数中进行默认更新的处理。另外,还可以使用:
void schedule(cocos2d::SEL_SCHEDULE(my_update_func)); void schedule(cocos2d::SEL_SCHEDULE(my_update_func), float interval); void schedule(cocos2d::SEL_SCHEDULE(my_update_func), float interval, unsigned int repeat, float delaty);
这三个重载函数可以调用自己定义的更新函数my_update_func,并且可以设置一些定时信息。
同样的,如果要取消可以使用:
this->unschedule(cocos2d::SEL_SCHEDULE(my_update_func));
这里,还有仅在一定时间后调用一次的方法:
this->scheduleOnce(cocos2d::SEL_SCHEDULE(my_update_func), float delaty);
开启update后,我们就可以在函数中进行我们的逻辑处理。
首先,是关于如何判断方块已经落下,我这里是判断其在连续的几次update中,y轴变化很微小,即判断其已经落下:
if(std::fabs(currentBlock->getPositionY() - lastPositionY) <= 0.5f && times >= 80)
同时,需要判断落下方块的位置,如果已经到达顶端,则game over:
if(currentBlock->getPositionX() >= visibleSize.width/2 - 50 && currentBlock->getPositionX() <= visibleSize.width/2 + 50 && currentBlock->getPositionY() >=visibleSize.height/2 + 220) { auto newScene = GameOver::createScene(score); Director::getInstance()->replaceScene(CCTransitionFade::create(1.5, newScene)); }
然后,是判断是否达到消行条件,如果达到消行条件,就应当进行消行处理:
float yStart = visibleSize.height/2 - 250; for(int i=0; i<20; i++) { float area = 0; for(int j=0; j<blockSet->size(); j++) { BaseBlock * sprite = blockSet->at(j); area += sprite->calculaArea(yStart + 25*i, yStart + 25*(i+1)); } if(area >= 6000) { Vector<BaseBlock *> * tempBlock = new Vector<BaseBlock *>(); for(int k=0; k<blockSet->size(); k++) { BaseBlock * sprite = blockSet->at(k); Vector<BaseBlock *> * vecShapes = sprite->doubleLineCutting(yStart + 25*i, yStart + 25*(i+1)); if(vecShapes != NULL) { if(vecShapes->size() == 1) { blockSet->erase(k); k--; this->removeChild(sprite); } else { blockSet->erase(k); k--; this->addChild(vecShapes->at(0), 2); tempBlock->pushBack(vecShapes->at(0)); this->addChild(vecShapes->at(1), 2); tempBlock->pushBack(vecShapes->at(1)); this->removeChild(sprite); } } } for(int k=0; k<tempBlock->size(); k++) { blockSet->pushBack(tempBlock->at(k)); } if(scoreBase == 0) scoreBase = 1; else scoreBase *= 2; } }
最后,就是关于如何计分。我这里计分方式是,每次下落+10分,每次消行,根据一次性消除的多少,计100、200、400、800...分。
因此,在判断方块落下时,添加代码:
score += 10;
在消行成功时:
score = score + scoreBase * 100;
最终将更新的分数显示在得分栏:
char * scoreStringTemp = new char[256]; std::sprintf(&scoreStringTemp[0], "%d", score); std::string scoreString = scoreStringTemp; scoreLabel->setString(scoreString);
同时这里需要生成新的下落的方块:
//产生下一个方块 void GameView::buildNextBlock() { //TODO Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); if(nextBlock == NULL) { currentBlock = randomBuildBlock(); } else { currentBlock = nextBlock; } currentBlock->setPosition(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2 + 220); currentBlock->getPhysicsBody()->setEnable(true); nextBlock = randomBuildBlock(); nextBlock->setPosition(origin.x + 415, visibleSize.height/2 + 200); nextBlock->getPhysicsBody()->setEnable(false); }