• Cocos2d 之FlyBird开发---GamePlay类


    |   版权声明:本文为博主原创文章,未经博主允许不得转载。

    这个是游戏的核心部分:(FlyBird游戏重中之重)

    • 创建一个物理世界(世界设置重力加速度)
    • 在物理世界中添加一个动态的刚体(小鸟)
    • 在物理世界中添加一个静态的刚体(地板)和一个顶部边界(Edge)
    • 在物理世界中添加一对浮动的刚体(Pipe),并设置线速度
    • 设置每次点击屏幕小鸟上升的加速度
    • 碰撞检测,判断游戏是否结束

    下面贴上代码:

    GamePlay.h

    #ifndef _GAME_PLAY_H_
    #define _GAME_PLAY_H_
     
    #define PTM_RATIO    32
     
    #include "cocos2d.h"
    #include "Box2DBox2D.h"
    #include "SimpleAudioEngine.h"
     
    //背景音乐平台控制
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
    #define MUSIC_FILE        "music/background.wav"
    #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
    #define MUSIC_FILE        "music/background.ogg"
    #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    #define MUSIC_FILE        "music/background.caf"
    #else
    #define MUSIC_FILE        "music/background.mp3"
    #endif // CC_PLATFOR_WIN32
     
    USING_NS_CC;
    using namespace CocosDenshion;
     
    class GamePlay : public cocos2d::Layer, public b2ContactListener
    {
    private:
         cocos2d::Sprite* backgroundA;
         cocos2d::Sprite* backgroundB;
         cocos2d::Sprite* ready;
         cocos2d::Sprite* tutorial;
         cocos2d::Sprite* bird;
         cocos2d::Sprite* land;
         cocos2d::Sprite* num;
         cocos2d::Sprite* upPipe;
         cocos2d::Sprite* downPipe;
         cocos2d::Sprite* pipeContainer;
         cocos2d::Sprite* model;
         cocos2d::Sprite* gameEnd;
         cocos2d::LabelTTF* score;
         cocos2d::LabelTTF* best;
         cocos2d::MenuItemImage* play;
         cocos2d::MenuItemImage* exit;
         b2World* world;
         b2Body* birdBody;
         b2Body* landBody;
         b2Body* downBody;
         b2Body* upBody;
         int bestScore;
         int times = 0;
     
    private:
         void replaceBackground(int);
         void tipInformation();
         void addBird();
         void addLand();
         void addPipe(float dt);
         void gameBegin(float dt);
         void gameOver();
         void timeAnimate();
         void upperBoundary();
         //int birdSelect(float);
     
    public:
         static cocos2d::Scene* createScene();
         virtual bool init();
         void initPhysicsWorld();
         virtual void update(float);
         /// Called when two fixtures begin to touch.
         virtual void BeginContact(b2Contact* contact);
         /** Callback function for multiple touches began.
         *
         * @param touches Touches information.
         * @param unused_event Event information.
         * @js NA
         */
         virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
         void goPlay(cocos2d::Ref* pSender);
         void goExit();
         CREATE_FUNC(GamePlay);
    };
     
    #endif // _GAME_PLAY_H_
    

     GamePlay.cpp

    #include "GamePlay.h"
    #include "GameUnit.h"
    #include "GameData.h"
     
    unit u3;
     
    cocos2d::Scene* GamePlay::createScene()
    {
         auto scene = Scene::create();
         auto layer = GamePlay::create();
         scene->addChild(layer);
         return scene;
    }
     
    bool GamePlay::init()
    {
         if (!Layer::init())
         {
                  return false;
         }
         SimpleAudioEngine::getInstance()->playBackgroundMusic(MUSIC_FILE, true);
         this->initPhysicsWorld();
         this->replaceBackground(1);
         this->tipInformation();
         this->upperBoundary();
         this->addLand();
         this->addBird();
         this->timeAnimate();
         //this->addPipe();
     
         //设置多点触屏事件的监听器
         auto listener = EventListenerTouchAllAtOnce::create();
         listener->onTouchesBegan = CC_CALLBACK_2(GamePlay::onTouchesBegan, this);
         //注册监听器
         _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
     
         //设置物理世界监听
         world->SetContactListener(this);
     
         scheduleOnce(schedule_selector(GamePlay::gameBegin), 3);
         //scheduleUpdate();
     
         return true;
    }
     
    void GamePlay::initPhysicsWorld()
    {
         //设置重力加速度为9.8;方向向下
         b2Vec2 gravity;
         gravity.Set(0.0f, -9.8f);
         //创建一个新的物理世界
         world = new b2World(gravity);
     
         //设置是否允许物体休眠
         world->SetAllowSleeping(true);
         //连续物理测试,防止发生非子弹特性的物体发生穿透现象
         world->SetContinuousPhysics(true);
    }
     
    void GamePlay::timeAnimate()
    {
         num = Sprite::create("bird/n1.png");
         num->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + (4 * u3.winSize().height) / 5));
         num->setScale(2);
         auto repeat = Repeat::create(Animate::create(u3.gameAnimate(4)), 1);
         num->runAction(repeat);
         this->addChild(num, 1);
    }
     
    void GamePlay::replaceBackground(int flag)
    {
         switch (flag)
         {
         case 1:
                  backgroundA = Sprite::create("background/light.png");
                  backgroundA->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                          u3.winOrigin().y + u3.winSize().height / 2));
                  backgroundA->setScale(u3.scaleX(backgroundA, u3.winSize()),
                          u3.scaleY(backgroundA, u3.winSize()));
                  this->addChild(backgroundA, 0);
                  break;
         case 2:
                  backgroundB = Sprite::create("background/night.png");
                  backgroundB->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                          u3.winOrigin().y + u3.winSize().height / 2));
                  backgroundB->setScale(u3.scaleX(backgroundB, u3.winSize()),
                          u3.scaleY(backgroundB, u3.winSize()));
                  this->addChild(backgroundB, 0);
                  break;
         default:
                  break;
         }
    }
     
    void GamePlay::tipInformation()
    {
         ready = Sprite::create("logo/text_ready.png");
         ready->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + u3.winSize().height - 3*ready->getContentSize().height));
         ready->setScale(2);
         this->addChild(ready, 1);
     
         tutorial = Sprite::create("logo/tutorial.png");
         tutorial->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + u3.winSize().height / 2));
         tutorial->setScale(2);
         this->addChild(tutorial, 1);
     
         //exit
         exit = MenuItemImage::create(
                  "button/exit_f.png",
                  "button/exit_b.png",
                  CC_CALLBACK_0(GamePlay::goExit, this)
                  );
         Menu* menu = Menu::create(exit, NULL);
         menu->setPosition(Vec2(u3.winOrigin().x + exit->getContentSize().width / 2,
                  u3.winOrigin().y + exit->getContentSize().height / 2));
         this->addChild(menu, 7);
    }
     
    void GamePlay::addBird()
    {
         bird = Sprite::create("bird/littleBird.png");
         bird->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 3,
                  u3.winOrigin().y + u3.winSize().height - 5 * (ready->getContentSize().height)));
         bird->setScale(1.5);
         auto repeat = RepeatForever::create(Animate::create(u3.gameAnimate(1)));
         bird->runAction(repeat);
         this->addChild(bird, 1);
     
         //创建刚体
         b2BodyDef birdBodyDef;
         birdBodyDef.type = b2_dynamicBody;
         birdBodyDef.position.Set(bird->getPosition().x / PTM_RATIO,
                  bird->getPosition().y / PTM_RATIO);
         //将刚体,精灵与世界关联起来
         birdBody = world->CreateBody(&birdBodyDef);
         birdBody->SetUserData(bird);
     
         //定义一个盒子
         b2PolygonShape birdBox;
         birdBox.SetAsBox(bird->getContentSize().width / 3 / PTM_RATIO,
                  bird->getContentSize().height / 3 / PTM_RATIO);
         //夹具
         b2FixtureDef fixtureDef;
         //设置夹具的形状
         fixtureDef.shape = &birdBox;
         birdBody->CreateFixture(&fixtureDef);
    }
     
    void GamePlay::update(float dt)
    {
         world->Step(dt, 8, 3);
         for (b2Body* bb = world->GetBodyList(); bb; bb = bb->GetNext())
         {
                  if (bb->GetUserData() != nullptr)
                  {
                          Sprite* sprite = (Sprite*)bb->GetUserData();
                          //设置精灵的当前的位置,通过取得精灵的位置乘上相应的像素,这里的PTM_RATIO为32个像素为1m,就可以判断出精灵的位置处于物理世界的何处
                          sprite->setPosition(Vec2(bb->GetPosition().x*PTM_RATIO,
                                   bb->GetPosition().y*PTM_RATIO));
                          //设置精灵的角度偏转
                          sprite->setRotation(0);
                  }
         }
    }
     
    void GamePlay::onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)
    {
         birdBody->SetLinearVelocity(b2Vec2(0, 5));
         //birdBody->SetLinearVelocity(b2Vec2(1, 5));
    }
     
    //添加地面
    void GamePlay::addLand()
    {
         //地板也是物理世界的一个刚体,是一个静态的刚体
         land = Sprite::create("background/land.png");
         land->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + land->getContentSize().height / 2));
         land->setScaleX(u3.winSize().width / 1.5*land->getContentSize().width);
         land->setScaleY(u3.winSize().height / (land->getContentSize().height * 3));
         this->addChild(land, 4);
     
         //创建刚体
         b2BodyDef landBodyDef;
         landBodyDef.type = b2_staticBody;
         landBodyDef.position.Set(u3.winSize().width / 2 / PTM_RATIO,
                  land->getPosition().y / PTM_RATIO);
     
         landBody = world->CreateBody(&landBodyDef);
         landBody->SetUserData(land);
     
         b2PolygonShape landShape;
         landShape.SetAsBox(u3.winSize().width / 2 / PTM_RATIO,
                  backgroundA->getContentSize().height / 2 / PTM_RATIO);
         //1.4*land->getContentSize().height / PTM_RATIO
         b2FixtureDef landFixtureDef;
         landFixtureDef.shape = &landShape;
         landBody->CreateFixture(&landFixtureDef);
    }
     
    void GamePlay::upperBoundary()
    {
         b2BodyDef upperBodyDef;
         //左下角
         upperBodyDef.position.Set(0, 0);
         //创建地面物体
         b2Body* upperBody = world->CreateBody(&upperBodyDef);
         //定义一个有边的形状
         b2EdgeShape upperBox;
     
         //顶部边界线
         upperBox.Set(b2Vec2(0, u3.winSize().height / PTM_RATIO),
                  b2Vec2(u3.winSize().width / PTM_RATIO, u3.winSize().height / PTM_RATIO));
         upperBody->CreateFixture(&upperBox, 0);
    }
     
    void GamePlay::addPipe(float dt)
    {
         times++;
     
         float randPipe = -rand() % 3;
         //down bar
         downPipe = Sprite::create("pipe/down.png");
         downPipe->setScaleY(u3.winSize().height / (downPipe->getContentSize().height*1.5));
         this->addChild(downPipe, 3);
         b2BodyDef downBodyDef;
         downBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
                  downPipe->getContentSize().height / 2 / PTM_RATIO + randPipe);
         // + land->getContentSize().height / PTM_RATIO
         downBodyDef.type = b2_kinematicBody;
         //修改速度可以提升游戏的难度
         downBodyDef.linearVelocity = b2Vec2(-2, 0);
         downBody = world->CreateBody(&downBodyDef);
         downBody->SetUserData(downPipe);
         b2PolygonShape downShape;
         downShape.SetAsBox(downPipe->getContentSize().width / 2 / PTM_RATIO,
                  1.6*downPipe->getContentSize().height / PTM_RATIO);
         b2FixtureDef downPipeFixture;
         downPipeFixture.shape = &downShape;
         downBody->CreateFixture(&downPipeFixture);
     
         upPipe = Sprite::create("pipe/upPipe.png");
         upPipe->setScaleY(u3.winSize().height / (upPipe->getContentSize().height*1.5));
         this->addChild(upPipe, 3);
         b2BodyDef upBodyDef;
         upBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
                  downPipe->getContentSize().height / PTM_RATIO + randPipe + 3 +2*upPipe->getContentSize().height / PTM_RATIO);
         // 
         upBodyDef.type = b2_kinematicBody;
         //修改速度可以提升游戏的难度
         upBodyDef.linearVelocity = b2Vec2(-2, 0);
         upBody = world->CreateBody(&upBodyDef);
         upBody->SetUserData(upPipe);
         b2PolygonShape upShape;
         upShape.SetAsBox(upPipe->getContentSize().width / 2 / PTM_RATIO,
                  1.6*upPipe->getContentSize().height / PTM_RATIO);
         b2FixtureDef upPipeFixture;
         upPipeFixture.shape = &upShape;
         upBody->CreateFixture(&upPipeFixture);
    }
     
    void GamePlay::gameOver()
    {
         //显示Game Over的Logo
         gameEnd = Sprite::create("logo/gameOver.png");
         gameEnd->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + u3.winSize().height - 3*gameEnd->getContentSize().height));
         gameEnd->setScale(2);
         this->addChild(gameEnd, 5);
     
         //显示奖章牌
         model = Sprite::create("logo/score_panel.png");
         model->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                  u3.winOrigin().y + u3.winSize().height / 2));
         model->setScale(u3.winSize().width / 1.5 / model->getContentSize().width,
                  u3.winSize().height / 4.5 / model->getContentSize().height);
         this->addChild(model, 5);
     
         //奖章
         Sprite* award = Sprite::create("logo/medals1.png");
         award->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2 - model->getContentSize().width*0.6,
                  u3.winOrigin().y + u3.winSize().height / 2));
         award->setScale(3);
         this->addChild(award, 6);
     
         //显示成绩
         score = LabelTTF::create("0", "Arial", 16);
         score->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
                  u3.winOrigin().y + u3.winSize().height / 2 + award->getContentSize().height));
         this->addChild(score, 7);
         //设置字体的颜色为黑色,并将成绩显示在panel面板上
         score->setColor(Color3B(0, 0, 0));
         score->setString(__String::createWithFormat("%5d", times - 1)->getCString());
     
         bestScore = GameData::getGameData();
         best = LabelTTF::create("0", "Arial", 16);
         best->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
                  u3.winOrigin().y + u3.winSize().height / 2 - 1.5*award->getContentSize().height));
         this->addChild(best, 7);
         best->setColor(Color3B(0, 0, 0));
         best->setString(__String::createWithFormat("%5d", bestScore - 1)->getCString());
         GameData::keepGameData(times);
     
         unscheduleUpdate();
         unschedule(schedule_selector(GamePlay::addPipe));
    }
     
    void GamePlay::gameBegin(float dt)
    {
         ready->setVisible(false);
         tutorial->setVisible(false);
         num->setVisible(false);
     
         scheduleUpdate();
         //修改时间可以提升游戏的难易程度
         schedule(schedule_selector(GamePlay::addPipe), 2);
    }
     
    void GamePlay::BeginContact(b2Contact* contact)
    {
         if (contact->GetFixtureA()->GetBody() == birdBody || contact->GetFixtureB()->GetBody() == birdBody)
         {
                  this->gameOver();
     
                  play = MenuItemImage::create(
                          "button/play.png",
                          "button/play.png",
                          CC_CALLBACK_1(GamePlay::goPlay, this)
                          );
                  play->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
                          u3.winOrigin().y + u3.winSize().height / 3));
                  Menu* menu = Menu::create(play, NULL);
                  menu->setPosition(Vec2::ZERO);
                  menu->setScale(1.5);
                  this->addChild(menu, 6);
         }
    }
     
    void GamePlay::goPlay(cocos2d::Ref* pSender)
    {
         times = 0;
         Director::getInstance()->replaceScene(TransitionFadeTR::create(1,
                  GamePlay::createScene()));
    }
     
    void GamePlay::goExit()
    {
         times = 0;
         unscheduleUpdate();
         unschedule(schedule_selector(GamePlay::addPipe));
     
         Director::getInstance()->end();
    }

    函数功能详见:http://www.cnblogs.com/geore/p/5800009.html

    效果图:

      

  • 相关阅读:
    NVelocity的基本用法
    awk字符串处理
    R中去除为NA的行--转载
    从Github上轻松安装R包—githubinstall包--转载
    志诺维思(北京)基因科技有限公司
    密码子优化--转载
    reshape2 数据操作 数据融合( cast)
    rsync数据同步工具
    R语言中的字符串处理函数
    R中的sub替换函数【转】
  • 原文地址:https://www.cnblogs.com/geore/p/5800131.html
Copyright © 2020-2023  润新知