cocos2dx3.3开发FlappyBird总结十六:游戏层实现

cocos2dx3.3开发FlappyBird总结十六:游戏层实现,第1张

概述游戏有三种状态,准备开始、游戏中、游戏结束,定义一个枚举来表示: /** * The status of game, it has three status. */typedef enum tag_GameState { /** The game hasn't started, but ready to start */ kGameStateReady = 1, /** The ga

游戏有三种状态,准备开始、游戏中、游戏结束,定义一个枚举来表示:

/** * The status of game,it has three status. */typedef enum tag_GameState {  /** The game hasn't started,but ready to start */  kGameStateReady = 1,/** The game has started,and the player is playing the game */  kGameStateStarted,/** The game has over,it means that the player has lost */  kGameStateOver} GameState;

游戏层与控制层需要通信,因此要遵守代理协议:

class GameScene : public cocos2d::Layer,public OptionDelegate

代理协议只有一个方法,就是点击屏幕事件监听回调:

/** * The OptionDelegate method overrIDe */  voID ontouch();

游戏层还需要与状态层通信,因此需要接收一个代理:

/** * The delegate of status. * When is setted,it will call StatusDelegate corresponding method on correct * time. */  CC_SYNTHESIZE(GameStatusDelegate*,_statusDelegate,StatusDelegate);

把状态层对象作为代理传到游戏层,就可以二者通信了。

下面看下初始化方法,这个是很重要的,添加物理特性,并监听触碰事件:

bool GameScene::init() {  if (!Layer::init()) {    return false;  }  auto size = Director::getInstance()->getVisibleSize();  auto origin = Director::getInstance()->getVisibleOrigin();  // Add the bird  auto bird = BirdSprite::getInstance();  bird->createBird();  auto body = PhysicsBody::create();  body->addShape(PhysiCSShapeCircle::create(kBirdRadius));  body->setDynamic(true);  body->setlineardamPing(0.0f);  body->setGravityEnable(false);  body->set@R_403_4602@Bitmask(0x01);  body->setCollisionBitmask(0x01);  body->setContactTestBitmask(0x01);  bird->setPhysicsBody(body);  bird->setposition(origin.x + size.wIDth / 3 - 5,origin.y + size.height / 2 + 5);  bird->setActionState(kActionStateIDle);  this->addChild(bird);  // Add the ground  _groundNode = Node::create();  auto groundBody = PhysicsBody::create();  auto groundSize = Size(kDesignWIDth,BackgroundLayer::getLandHeight());  groundBody->addShape(PhysiCSShapeBox::create(groundSize));  groundBody->setDynamic(false);  groundBody->setlineardamPing(0.0f);  groundBody->set@R_403_4602@Bitmask(0x01);  groundBody->setContactTestBitmask(0x01);  groundBody->setCollisionBitmask(0x01);  _groundNode->setPhysicsBody(groundBody);  _groundNode->setposition(groundSize.wIDth / 2,groundSize.height);  this->addChild(_groundNode);  // land  // Add the land1 and land2  _land1 = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("land"));  _land1->setAnchorPoint(Vec2::ZERO);  _land1->setposition(Vec2::ZERO);  this->addChild(_land1,30);  _land2 = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("land"));  _land2->setAnchorPoint(Vec2::ZERO);  _land2->setposition(Vec2(_land1->getContentSize().wIDth - 2.0f,0));  this->addChild(_land2,30);  // Add a timer to update the land  _shiftLand = schedule_selector(GameScene::scrollLand);  this->schedule(_shiftLand,0.01f);  // will call update(float delta) method  this->scheduleUpdate();  // Add contact Listener  //  // If body->get@R_403_4602@Bitmask() & groundBody->getContactTestBitmask() == 1  // Then we can Listen the physics touch event,otherwise not.  //  // If body->get@R_403_4602@Bitmask() & groundBody->getCollisionBitmask() == 1  // Then the bird and the ground can collIDe,otherwise not.  auto Listener = EventListenerPhysicsContact::create();  Listener->onContactBegin = CC_CALLBACK_1(GameScene::onContactBegin,this);  this->getEventdispatcher()->addEventListenerWithSceneGraPHPriority(Listener,this);  return true;}

要想让A和B能够在相碰时,发出事件,规则如下:
// If body->get@R_403_4602@Bitmask() & groundBody->getContactTestBitmask() == 1
// Then we can Listen the physics touch event,otherwise not.
要想让A和B能够发生冲突并发出事件,规则如下:
//
// If body->get@R_403_4602@Bitmask() & groundBody->getCollisionBitmask() == 1
// Then the bird and the ground can collIDe,otherwise not.

如果不添加,默认情况下是不会监听到的,刚开始我就遇到此问题,然后通过百度才明白原因。

下面是创建场景,需要把背景层、控制层、状态层、游戏层添加到场景中:

Scene* GameScene::createScene() {  // create a scene with physics world  // 场景需要使用物理世界来创建,否则添加的物理特性就无效  auto scene = Scene::createWithPhysics();  if (scene->getPhysicsWorld()) {    scene->getPhysicsWorld()->setGravity(Vect(0,-900));  } else {    cclOG("Error: Game scene get physics world,but it is nullptr");  }  // background layer  auto backgroundLayer = BackgroundLayer::create();  if (backgroundLayer) {    scene->addChild(backgroundLayer);  }  // game layer  auto gameLayer = GameScene::create();  // status layer  auto statusLayer = StatusLayer::create();  if (gameLayer) {    gameLayer->setPhysicsWorld(scene->getPhysicsWorld());    // 游戏层与状态层是需要通信的,把状态层作为游戏层的代理     gameLayer->setStatusDelegate(statusLayer);    gameLayer->setTag(kGameLayerTag);    scene->addChild(gameLayer);  }  if (statusLayer) {    scene->addChild(statusLayer);  }  // option layer  auto optionLayer = OptionLayer::create();  if (optionLayer) {  // 状态层与游戏层是需要通信的,把游戏层作为状态层的代理    optionLayer->setoptionDelegate(gameLayer);    scene->addChild(optionLayer);  }  return scene;}

添加水管,给水管也添加物理特性,就可以让小鸟与水管在接触时,发出相碰事件

voID GameScene::createPipes() {  // create pipes  auto size = Director::getInstance()->getVisibleSize();  for (int i = 0; i < kPipePairCount; ++i) {    auto pipeUp = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("pipe_up"));    //pipeUp->setposition(0,<#float y#>)    auto pipeDown = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("pipe_down"));    pipeDown->setposition(0,kPipeHeight + kPipeupdowndistance);    auto pipeNode = Node::create();    pipeNode->setposition(size.wIDth + i * kPipeInterval + kWaitdistance,getRandomPipeHeight());    pipeNode->addChild(pipeDown,0,kPipeDownTag);    pipeNode->addChild(pipeUp,kPipeUpTag);    // Add physics to pipe    auto body = PhysicsBody::create();    auto Box = PhysiCSShapeBox::create(pipeDown->getContentSize(),PHYSICSSHAPE_MATERIAL_DEFAulT,Vec2(0,kPipeHeight + kPipeupdowndistance));    body->addShape(Box);    body->addShape(PhysiCSShapeBox::create(pipeUp->getContentSize()));    body->setDynamic(false);// If body->get@R_403_4602@Bitmask() & 小鸟的物理body>->getCollisionBitmask() == 1// 小鸟与水管接触才会发出事件    body->set@R_403_4602@Bitmask(0x01);    body->setContactTestBitmask(0x01);    body->setCollisionBitmask(0x01);    pipeNode->setPhysicsBody(body);    pipeNode->setTag(kPipeNewTag);    this->addChild(pipeNode);    _pipes.pushBack(pipeNode);  }}

小鸟通过水管检测:

voID GameScene::checkHit() {  for (auto pipe : _pipes) {    if (pipe->getTag() == kPipeNewTag) {      // 通过一根      if (pipe->getpositionX() < BirdSprite::getInstance()->getpositionX()) { CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sfx_point.ogg");        ++_currentscore;        if (this->getStatusDelegate()) {          this->getStatusDelegate()->onGamePlaying(_currentscore);        }        pipe->setTag(kPipePassedTag);      }    }  }}

通过遍历所有水管,如果当前是显示在屏幕上新的水管,再判断与小鸟的X坐标,来判断小鸟是否通过了水管。 当通过后,又把水管设置为已经通过的水管,如此重复使用。

总结

以上是内存溢出为你收集整理的cocos2dx3.3开发FlappyBird总结十六:游戏层实现全部内容,希望文章能够帮你解决cocos2dx3.3开发FlappyBird总结十六:游戏层实现所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1050100.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存