//
// GameLayer.cpp
// FlappyBird
//
// Created by DoubleHH on 14-3-13.
//
//
#include "GameLayer.h"
#include "BBButton.h"
const int ZORDER_GROUND = 2;
const int ZORDER_COLLISION = 1;
const int ZORDER_ROLE = 10;
const int ZORDER_COUNTDOWN = 11;
const float INTERVAL_COLLISION = 150.0f;
GameLayer::~GameLayer() {
CC_SAFE_RELEASE_NULL(mGrounds);
CC_SAFE_RELEASE_NULL(mCollisionArray);
}
CCScene *GameLayer::scene() {
CCScene *scene = CCScene::create();
scene->addChild(GameLayer::create());
return scene;
}
bool GameLayer::init() {
bool bRet = false;
do {
CC_BREAK_IF(!CCLayer::init());
extraInit();
bRet = true;
} while (0);
return bRet;
}
void GameLayer::extraInit() {
initRole();
initGround();
initCollisions();
setRoleState(ROLE_STATE_JUMP_DOWN);
setTouchEnabled(false);
BBButton *button = BBButton::create(CCSizeMake(200, 60), this, bbButtonFunI_selector(GameLayer::restart), NULL, NULL, NULL, NULL, "Play Again");
button->mLabel->setFontSize(30);
button->setPosition(CCPoint(getContentSize().width - button->getContentSize().width, getContentSize().height - button->getContentSize().height));
button->mDependedTarget = this;
this->addChild(button, 10);
setScore(0);
beginCountdown(3);
}
void GameLayer::mainUpdate(float dt) {
if (getIsPaused()) {
return;
}
updateGround(dt);
updateCollisions(dt);
roleUpdate(dt);
updateScore();
}
#pragma mark - Game Control
void GameLayer::gameOver() {
this->unschedule(schedule_selector(GameLayer::mainUpdate));
setIsPaused(true);
CCMessageBox("Where is a will, There is a way!", "Game over");
}
void GameLayer::restart() {
setScore(0);
resetCollisions();
resetRole();
beginCountdown(3);
}
void GameLayer::resetRole() {
mRole->setPosition(ccp(getContentSize().width * .5, getContentSize().height * .5));
setRoleState(ROLE_STATE_JUMP_DOWN);
}
void GameLayer::resetCollisions() {
float x = getStartCollsionX();
float interval = BarPipe::getSize().width + INTERVAL_COLLISION;
for (int i=0; i<mCollisionArray->count(); ++i) {
BarPipe *pBar = (BarPipe *)mCollisionArray->objectAtIndex(i);
pBar->setRandomY();
pBar->setBarPositionX(x);
pBar->setIsPassed(false);
x += interval;
}
}
float GameLayer::getStartCollsionX() {
return (CCDirector::sharedDirector()->getWinSize().width * .7);
}
#pragma mark - Countdown
void GameLayer::preCountdown() {
setTouchEnabled(false);
setIsPaused(true);
}
#define TagCountdown 108474
void GameLayer::beginCountdown(int second) {
preCountdown();
setCountdownNum(second);
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCLabelTTF *label = CCLabelTTF::create(CCString::createWithFormat("%d", getCountdownNum())->getCString(), "ArialMT", 100);
label->setColor(ccRED);
label->setAnchorPoint(ccp(.5, .5));
label->setPosition(ccp(size.width * .5, size.height * .5));
this->addChild(label, ZORDER_COUNTDOWN);
this->schedule(schedule_selector(GameLayer::countdownSeconds), 0.8);
label->setTag(TagCountdown);
doCountdownAnimation(label);
}
void GameLayer::countdownSeconds() {
CCLabelTTF *label = (CCLabelTTF *)getChildByTag(TagCountdown);
if (label) {
setCountdownNum(getCountdownNum() - 1);
if (getCountdownNum() < 1) {
label->removeFromParent();
label = NULL;
this->unschedule(schedule_selector(GameLayer::countdownSeconds));
countdonwDone();
return;
}
label->setString(CCString::createWithFormat("%d", getCountdownNum())->getCString());
doCountdownAnimation(label);
}
}
void GameLayer::countdonwDone() {
setTouchEnabled(true);
setIsPaused(false);
this->schedule(schedule_selector(GameLayer::mainUpdate), 0.016f);
}
void GameLayer::doCountdownAnimation(CCNode *node) {
node->runAction(CCSequence::create(CCScaleTo::create(0.3, 3),
CCScaleTo::create(0.15, 1.0),
NULL));
}
#pragma mark - Score
void GameLayer::setScore(int var) {
score = var;
if (!mScoreLabel) {
CCLabelTTF *label = CCLabelTTF::create(CCString::createWithFormat("%d", getScore())->getCString(), "ArialMT", 30);
label->setColor(ccYELLOW);
label->setAnchorPoint(ccp(0, .5));
label->setPosition(ccp(50, getContentSize().height * 0.9));
this->addChild(label, ZORDER_COUNTDOWN);
mScoreLabel = label;
}
mScoreLabel->setString(CCString::createWithFormat("Score: %d", getScore())->getCString());
}
int GameLayer::getScore() {
return score;
}
/**
更新用户的分数
**/
void GameLayer::updateScore() {
for (int i=0; i<mCollisionArray->count(); ++i) {
BarPipe *pBarPipe = (BarPipe *)mCollisionArray->objectAtIndex(i);
if (!pBarPipe->getIsPassed() &&
(pBarPipe->getBarPositionX() + pBarPipe->getSize().width) < mRole->getPositionX()) {
pBarPipe->setIsPassed(true);
setScore(getScore() + 1);
}
}
}
#pragma mark - Touch
void GameLayer::registerWithTouchDispatcher() {
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -1, true);
}
void GameLayer::onExit() {
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool GameLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) {
setRoleState(ROLE_STATE_JUMP_UP);
return true;
}
#pragma mark - Role
void GameLayer::initRole() {
CCSize size = CCDirector::sharedDirector()->getWinSize();
mRole = CCSprite::create("bird.png");
mRole->setAnchorPoint(ccp(0, 0));
mRole->setPosition(ccp(size.width * .5, size.height * .5));
this->addChild(mRole, ZORDER_ROLE);
}
void GameLayer::roleUpdate(float dt) {
switch (getRoleState()) {
case ROLE_STATE_JUMP_UP: {
this->roleJumpUpLogic();
break;
}
case ROLE_STATE_JUMP_DOWN: {
this->roleJumpDownLogic();
break;
}
default:
break;
}
}
void GameLayer::setRoleState(ROLE_STATE var) {
switch (var) {
case ROLE_STATE_JUMP_UP: {
CCLOG("开始上升");
setRoleYSpeed(getRoleConstYSpeed());
break;
}
case ROLE_STATE_JUMP_DOWN: {
CCLOG("开始下降");
setRoleYSpeed(0);
break;
}
default:
break;
}
roleState = var;
}
void GameLayer::roleJumpDownLogic() {
/**
1, 先判断是否到地面下了
2, 检测右边的碰撞
3, 检测下面的碰撞
**/
float roleY = mRole->getPositionY();
roleY -= getRoleYSpeed();
if (roleY < getGroundHeight()) {
gameOver();
CCLOG("正在下降, 撞地了");
return;
}
BarPipe *willCollisionBar = getWillCollisionBar();
if (isCollisionWithBar(COLL_STATE_RIGHT, willCollisionBar)) {
gameOver();
CCLOG("正在下降, 右边发生碰撞");
return;
}
if (isCollisionWithBar(COLL_STATE_BOTTOM, willCollisionBar)) {
gameOver();
CCLOG("正在下降, 下边发生碰撞");
return;
}
mRole->setPositionY(roleY);
setRoleYSpeed(getRoleYSpeed() + getRoleAccelerate());
}
void GameLayer::roleJumpUpLogic() {
/**
1, 检测是否碰到天花板了
2, 判断速度是否小于等于零了
3, 检测右边的碰撞
4. 检测上边的碰撞
**/
float roleY = mRole->getPositionY();
roleY += getRoleYSpeed();
// 判断是否过了屏幕上方
if (roleY + mRole->getContentSize()
- 1
- 2
前往页