一、控制层

在OptionLayer层中,我们实现了触摸事件的监听

bool OptionLayer::init()
{
if(Layer::init()){
auto dispatcher = Director::getInstance()->getEventDispatcher();
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(OptionLayer::onTouchesBegan, this);
dispatcher->addEventListenerWithSceneGraphPriority(listener, this);

	return true;
}else {
	return false;
}

}

void OptionLayer::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)
{
this->delegator->onTouch();
}
在头文件OptionLayer.h中定义了delegator

CC_SYNTHESIZE(OptionDelegate*, delegator, Delegator);
还有OptionDelegate类

class OptionDelegate
{
public:
virtual void onTouch() = 0;
};
二、控制层与游戏层的关系

游戏层GameLayer和控制层OptionLayer通过代理OptionDelegate来进行通讯

游戏层继承OptionDelegate实现onTouch()方法

class GameLayer : public Layer , public OptionDelegate;
在游戏主场景GameScene中将两者联系起来

	// Add operation layer to control the game
	auto optionLayer = OptionLayer::create();
	if(optionLayer) {
		optionLayer->setDelegator(gameLayer);
		this->addChild(optionLayer);
	}

三、游戏层

1、游戏状态

游戏有三种状态:准备、开始、结束

typedef enum _game_status {
GAME_STATUS_READY = 1,
GAME_STATUS_START,
GAME_STATUS_OVER
} GameStatus;
2、添加小鸟

在上一节中我们已经完成了小鸟类的封装,我们先在GameLayer.h中声明这只小鸟

BirdSprite *bird;
设置物理引擎的相关属性并添加到游戏层中

// Add the bird
this->bird = BirdSprite::getInstance();
this->bird->createBird();
PhysicsBody *body = PhysicsBody::create();
body->addShape(PhysicsShapeCircle::create(BIRD_RADIUS));
body->setCategoryBitmask(ColliderTypeBird);
body->setCollisionBitmask(ColliderTypeLand & ColliderTypePip);
body->setContactTestBitmask(ColliderTypeLand | ColliderTypePip);
body->setDynamic(true);
body->setLinearDamping(0.0f);
body->setGravityEnable(false);
this->bird->setPhysicsBody(body);
this->bird->setPosition(origin.x + visiableSize.width*1/3 - 5,origin.y + visiableSize.height/2 + 5);
this->bird->idle();
this->addChild(this->bird);
游戏进行过程当中,每次点击屏莫的时候,给小鸟设置一个向上的初速度:

this->bird->getPhysicsBody()->setVelocity(Vect(0, 260)

3、水管的添加

水管的添加,主要是通过createPips()函数来生成水管

void GameLayer::createPips() {
// Create the pips
for (int i = 0; i < PIP_COUNT; i++) {
Size visibleSize = Director::getInstance()->getVisibleSize();
Sprite *pipUp = Sprite::createWithSpriteFrameName("pipe_up.png");
Sprite *pipDown = Sprite::createWithSpriteFrameName("pipe_down.png");
Node *singlePip = Node::create();

    // bind to pair
    pipDown->setPosition(0, PIP_HEIGHT + PIP_DISTANCE);
	singlePip->addChild(pipDown, 0, DOWN_PIP);
    singlePip->addChild(pipUp, 0, UP_PIP);
    singlePip->setPosition(visibleSize.width + i*PIP_INTERVAL + WAIT_DISTANCE, this->getRandomHeight());
	auto body = PhysicsBody::create();
	auto shapeBoxDown = PhysicsShapeBox::create(pipDown->getContentSize(),PHYSICSSHAPE_MATERIAL_DEFAULT, Point(0, PIP_HEIGHT + PIP_DISTANCE));
	body->addShape(shapeBoxDown);
	body->addShape(PhysicsShapeBox::create(pipUp->getContentSize()));
	body->setDynamic(false);
	body->setContactTestBitmask(true);
	singlePip->setPhysicsBody(body);
    singlePip->setTag(PIP_NEW);

    this->addChild(singlePip);
    this->pips.push_back(singlePip);
}

}
一组水管由上下2半根组成,用vector容器添加两组管道,每次出现在屏幕中的管子只有两组,当一组消失在屏幕范围内则重设置其横坐标

// move the pips
for (auto singlePip : this->pips) {
    singlePip->setPositionX(singlePip->getPositionX() - 2);
    if(singlePip->getPositionX() < -PIP_WIDTH) {
        singlePip->setTag(PIP_NEW);
        Size visibleSize = Director::getInstance()->getVisibleSize();
        singlePip->setPositionX(visibleSize.width);
        singlePip->setPositionY(this->getRandomHeight());
    }
}

4、碰撞检查

在GameLayer初始化的时候,我们创建了一个碰撞监听:

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(GameLayer::onContactBegin, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);

一旦出现碰撞,则进入游戏结束状态

bool GameLayer::onContactBegin(PhysicsContact& contact) {
this->gameOver();
return true;
}

项目源码托管在Github:https://github.com/smiger/FlappyBird