zoukankan      html  css  js  c++  java
  • cocos2dx 实现flappybird

    前两天在博客园看到网友实现的一个网页版的flappy bird,挂在360游戏平台,玩了一会儿得分超低,就很想自己做一个。刚好这两天炫舞的活都清了,就弄一下玩玩。

    效果图

    布局类GameScene.h

    #ifndef GAMESCENE_BIRD
    #define  GAMESCENE_BIRD
    
    #include "cocos2d.h"
    
    #include "Box2D/Box2D.h"
    
    #include "SimpleAudioEngine.h"
    USING_NS_CC;
    class Cbird;
    class CPipe;
    class CGameScene :public cocos2d::CCLayer
    {
    public:
         CCSprite * _background;
        /* CPipe * _pipe;*/
         CCSpriteBatchNode * _gameBatchNode;
         Cbird * m_bird;
        /* CCArray *m_pipes;*/
         CPipe *_pipes;
        // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
        virtual bool init();  
    
        // there's no 'id' in cpp, so we recommand to return the exactly class pointer
        static cocos2d::CCScene* scene();
    
        // a selector callback
        void menuCloseCallback(CCObject* pSender);
    
        // implement the "static node()" method manually
        CREATE_FUNC(CGameScene);
    
        virtual void ccTouchesBegan(CCSet* pTouches, CCEvent* event);
        virtual void ccTouchesEnded(CCSet* pTouches, CCEvent* event);
        void update(float dt);
        void startGame (CCObject* pSender);
    private:
        enum{        
            GAMEREAD=0,
            GAMEOVER,
            BIRDFLY,
            BIRDDIE,
        };
        enum{
            TAG_LOGO,
            TAG_OVER,
            TAG_BUTTON,
            TAG_BESTSCORE,
            TAG_CURRSCORE,
        };
        int m_gamestate;
    };
    #endif

    GameScene.cpp

    #include "GameScene.h"
    #include "Bird.h"
    #include "Pipe.h"
    using namespace cocos2d;
    
    
    cocos2d::CCScene* CGameScene::scene()
    {
        CCScene * scene = NULL;
        do 
        {
            // 'scene' is an autorelease object
            scene = CCScene::create();
            CC_BREAK_IF(! scene);
    
            // 'layer' is an autorelease object
            CGameScene *layer = CGameScene::create();
            CC_BREAK_IF(! layer);
    
            // add layer as a child to scene
            scene->addChild(layer);
        } while (0);
    
        // return the scene
        return scene;
    }
    
    bool CGameScene::init()
    {
        bool bRet = false;
        do 
        {
            this->setTouchEnabled(true);
            //设置游戏背景
            CCSprite * bg = CCSprite::create("bird_bg.png");
            bg->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width * 0.5f, CCDirector::sharedDirector()->getWinSize().height * 0.5f));
            this->addChild(bg, 0);
    
            //CCSpriteFrameCache(精灵帧缓存)主要用来存放CCSpriteFrame,它没有提供特别的属性,而是提供一系列用于管理CCSpriteFrame的方法
            CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("bird.plist","bird.png");
            _gameBatchNode = CCSpriteBatchNode::create("bird.png", 200);
            this->addChild(_gameBatchNode, 1);
    
            CCSprite * repeat;
    
            _background = CCSprite::createWithSpriteFrameName("bird_bg.png");
            _background->setAnchorPoint(ccp(0,0));
            _gameBatchNode->addChild(_background, 0);
    
            repeat = CCSprite::createWithSpriteFrameName("bird_bg.png");
            repeat->setAnchorPoint(ccp(0,0));
            repeat->setPosition(ccp(repeat->getContentSize().width - 1, 0));
            _background->addChild(repeat, 0);
    
            repeat = CCSprite::createWithSpriteFrameName("bird_bg.png");
            repeat->setAnchorPoint(ccp(0,0));
            repeat->setPosition(ccp(2 * (repeat->getContentSize().width - 1), 0));
            _background->addChild(repeat, 0);
    
    
            //设置水管
        /*    _pipe =new CPipe;
            _pipe->SetLayer(_gameBatchNode);
    
            m_pipes = CCArray::arrayWithCapacity(4);*/
            _pipes = new CPipe[4];
            for(int i = 0;i < 4;i ++){
                _pipes[i].init();
                _pipes[i].SetLayer(_gameBatchNode);
            }
    
    
            //加入logo
            CCSprite* _intro = CCSprite::createWithSpriteFrameName("bird_logo.png");
            _intro->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width * 0.5f, CCDirector::sharedDirector()->getWinSize().height * 0.7f));
            _intro->setTag(TAG_LOGO);
            _gameBatchNode->addChild(_intro, 10);
    
            //加入gamgover logo
            CCSprite* _over = CCSprite::createWithSpriteFrameName("bird_gameover.png");
            _over->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width * 0.5f, CCDirector::sharedDirector()->getWinSize().height * 0.7f));
            _over->setTag(TAG_OVER);
            _over->setVisible(false);
            _gameBatchNode->addChild(_over, 10);
    
            //add menu
            CCSprite * menuItemOn;
            CCSprite * menuItemOff;
            //菜单有两个状态,平时展示的样子和点击的样子
            menuItemOn = CCSprite::createWithSpriteFrameName("bird_start_btn.png");
            menuItemOff = CCSprite::createWithSpriteFrameName("brid_start_btn_pressed.png");
            //New Game 菜单
            CCMenuItemSprite * starGametItem = CCMenuItemSprite::create(
                menuItemOff,
                menuItemOn,
                this,
                //这个最重要,点击菜单调用系统哪个方法
                menu_selector(CGameScene::startGame));
    
            CCMenu*_mainMenu = CCMenu::create( starGametItem, NULL);//创建菜单
            _mainMenu->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width * 0.5f, CCDirector::sharedDirector()->getWinSize().height * 0.5f));
            _mainMenu->setTag(TAG_BUTTON);
            this->addChild(_mainMenu,10);
    
            CCLabelBMFont* bestscore = CCLabelBMFont::create("0", "font.fnt");
            bestscore->setPosition(CCPoint(CCDirector::sharedDirector()->getWinSize().width / 15, CCDirector::sharedDirector()->getWinSize().height / 4 * 3));        
            bestscore->setVisible(false);
            bestscore->setTag(TAG_BESTSCORE);
            this->addChild(bestscore,10);
    
            CCLabelBMFont* currscore = CCLabelBMFont::create("0", "font.fnt");
            currscore->setPosition(CCPoint(CCDirector::sharedDirector()->getWinSize().width / 15, CCDirector::sharedDirector()->getWinSize().height / 4 * 3));        
            currscore->setVisible(false);
            currscore->setTag(TAG_CURRSCORE);
            this->addChild(currscore,10);
    
            m_bird = Cbird::create();
            CC_BREAK_IF(! m_bird);
    
            // Place the sprite on the center of the screen
            //pSprite->setPosition(ccp(size.width/2, size.height/2));
    
            // Add the sprite to HelloWorld layer as a child layer.
            _gameBatchNode->addChild(m_bird, 100);
    
            bRet = true;
            this->schedule(schedule_selector(CGameScene::update));
            m_gamestate = GAMEREAD;
        } while (0);
    
        return bRet;
    }
    
    void CGameScene::menuCloseCallback( CCObject* pSender )
    {
       CCDirector::sharedDirector()->end();
    }
    
    void CGameScene::ccTouchesBegan( CCSet* pTouches, CCEvent* event )
    {
    }
    
    void CGameScene::ccTouchesEnded( CCSet* pTouches, CCEvent* event )
    {
        if (m_gamestate == BIRDFLY)
        {
            m_bird->SetFlyUp();
        }
    }
    void CGameScene::update(float dt)
    {
        //if (_pipe)
        //{
        //    _pipe->update(dt);
        //}
        //CPipe * pipe = (CPipe *)(m_pipes->objectAtIndex(0));
        //if (pipe)
        //{    
        _pipes[0].StartGame();
        for(int i = 0;i <3;i ++){
            //CPipe * _pipe = (CPipe *)(m_pipes->objectAtIndex(i));
            //CPipe * _pipe2 = (CPipe *)(m_pipes->objectAtIndex(i+1));
            if (_pipes[i].isStart())
            {
                if (_pipes[i].getPositionX()+213<=_pipes[i+1].getPositionX())
                {
                    _pipes[i+1].StartGame();
                }
            }
        }
        if (m_bird->getPositionY()<=0)
        {
            m_gamestate = BIRDDIE;
        }
        if (m_gamestate == BIRDFLY)
        {
            for(int i = 0;i <4;i ++){
                _pipes[i].update(dt);
            }
        }
        for(int i = 0;i <4;i ++){
            if(_pipes[i].CheckCollision(m_bird->getPositionX(), m_bird->getPositionY()))
            {
                m_gamestate = BIRDDIE;
    
                _gameBatchNode->getChildByTag(TAG_LOGO)->setVisible(false);
                _gameBatchNode->getChildByTag(TAG_OVER)->setVisible(true);
                this->getChildByTag(TAG_BUTTON)->setVisible(true);
                break;
            }
        }
    
        CCLabelBMFont* scoreSprite = (CCLabelBMFont*)this->getChildByTag(TAG_BESTSCORE);
        CCString* s = CCString::createWithFormat("%d", CPipe::GetScore());
        scoreSprite->setString(s->getCString());
        //}
    
    }
    
    void CGameScene::startGame (CCObject* pSender) {
        m_gamestate = BIRDFLY;
        _gameBatchNode->getChildByTag(TAG_LOGO)->setVisible(false);
        _gameBatchNode->getChildByTag(TAG_OVER)->setVisible(false);
        this->getChildByTag(TAG_BUTTON)->setVisible(false);
        m_bird->ResetBird();
        m_bird->GameStart();
        for(int i = 0;i <4;i ++){
            _pipes[i].ReSetPositionX();
            _pipes[i].GameOver();
        }
    
        CCLabelBMFont* scoreSprite = (CCLabelBMFont*)this->getChildByTag(TAG_BESTSCORE);
        scoreSprite->setVisible(true);
    }

    水管Pipe类

    #ifndef _PIPE_
    #define  _PIPE_
    #include "cocos2d.h"
    #include "GameScene.h"
    USING_NS_CC;
    class CPipe:public CCObject{
    private:
        CCSprite* m_upipe;
        CCSprite* m_dpipe;
        int relativeHight;
        enum{
            PLYAYING=0,
            OVER,
        };
        int m_gamestate;
        float updatetime;
        bool canaddscore;
    public:
        CPipe();
        ~CPipe();
        void ReSetPositionX();
        void update(float times);
        bool CheckCollision(int x, int y);
        void StartGame();
        void GameOver();
        void SetLayer(CCSpriteBatchNode* layer);
        float getPositionX();
        bool isStart();
        void init();
        static int GetScore();
    };
    #endif
    
    #include "Pipe.h"
    static int m_score = 0;
    CPipe::CPipe()
    :m_gamestate(OVER),
    updatetime(0.0),
    canaddscore(false)
    {
        //生成随机数
        float rheight = CCRANDOM_MINUS1_1();
        //设置上水管
        m_upipe = CCSprite::createWithSpriteFrameName("obstacle_up.png");
        m_upipe->setAnchorPoint(ccp(0,0));
        m_upipe->setPosition(ccp(852,306+rheight*100));
        m_upipe->retain();
        //设置下水管
        m_dpipe = CCSprite::createWithSpriteFrameName("obstacle_down.png");
        m_dpipe->setAnchorPoint(ccp(0,1));
        m_dpipe->setPosition(ccp(852,206+rheight*100));
        m_dpipe->retain();
        //this->schedule(schedule_selector(CPipe::update));
    }
    
    CPipe::~CPipe()
    {    
    
    
    }
    
    void CPipe::ReSetPositionX()
    {
        //生成随机数
        float rheight = CCRANDOM_MINUS1_1();
        m_upipe->setPosition(ccp(852,306+rheight*100));
        m_dpipe->setPosition(ccp(852,206+rheight*100));
        canaddscore = true;
    }
    
    void CPipe::update( float times )
    {
        //updatetime +=dt;
        //if (updatetime >= 0.4)
        //{
        //    updatetime = 0.0;
        //}
        if (m_gamestate == PLYAYING)
        {
            int pox = m_upipe->getPositionX()-3;
            if (pox <=-52)
            {
                pox = 852;
                ReSetPositionX();
            }
            m_upipe->setPositionX(pox);
            m_dpipe->setPositionX(pox);
            if ( m_upipe->getPositionX()<CCDirector::sharedDirector()->getWinSize().width*0.36f-52&&canaddscore)
            {
                m_score++;
                canaddscore = false;
            }
    
        }
    }
    
    bool CPipe::CheckCollision( int x, int y )
    {
        if (x<m_upipe->getPositionX()+52&&x>m_upipe->getPositionX())
        {
            if (y>m_upipe->getPositionY()||y<m_dpipe->getPositionY())
            {
                return true;
            }
        }
        return false;
    }
    
    void CPipe::StartGame()
    {
        m_gamestate = PLYAYING;
    }
    
    void CPipe::GameOver()
    {
        m_gamestate = OVER;
        m_score = 0;
    }
    
    void CPipe::SetLayer( CCSpriteBatchNode* layer )
    {
        layer->addChild(m_upipe, 10);
        layer->addChild(m_dpipe, 10);
    }
    
    float CPipe::getPositionX()
    {
        return m_dpipe->getPositionX();
    }
    
    bool CPipe::isStart()
    {
        return m_gamestate==PLYAYING;
    }
    
    void CPipe::init()
    {
        m_gamestate = OVER;
        //生成随机数
        float rheight = CCRANDOM_MINUS1_1();
        //设置上水管
        m_upipe = CCSprite::createWithSpriteFrameName("obstacle_up.png");
        m_upipe->setAnchorPoint(ccp(0,0));
        m_upipe->setPosition(ccp(852,306+rheight*100));
        m_upipe->retain();
        //设置下水管
        m_dpipe = CCSprite::createWithSpriteFrameName("obstacle_down.png");
        m_dpipe->setAnchorPoint(ccp(0,1));
        m_dpipe->setPosition(ccp(852,206+rheight*100));
        m_dpipe->retain();
    }
    
    int CPipe::GetScore()
    {
        return m_score;
    }

    小鸟类CBird

    #ifndef _BIRD_
    #define _BIRD_
    
    #define BIRDFALLSPEED 4
    #define BIRDGRAVITY 1
    #include "cocos2d.h"
    #include "GameScene.h"
    USING_NS_CC;
    
    typedef enum
    {
        playerRead,//等待游戏开始
        PlayerFlying,//主角在往上飞
        PlayerFalling,//主角在降落
        PlayerDying//主角死亡
    
    } PlayerState; 
    
    class Cbird:public CCSprite{
        CCAction * m_flyAnimation;
        CCAction * m_fallAnimation;
        CCAction * m_NormalAnimation;
        bool m_isfalling;
        PlayerState m_state;
        CCSize _screenSize;
    public:
        //定义变量,并且直接定义默认的get/set方法
        CC_SYNTHESIZE(CCPoint, _nextPosition, NextPosition);
    
        CC_SYNTHESIZE(float, _width, Width);
    
        CC_SYNTHESIZE(float, _height, Height);
    
        CC_SYNTHESIZE(CCPoint, _vector, Vector);
    public: 
        Cbird();
        ~Cbird();
        static Cbird * create (void);
        static Cbird * ShareBird(void);
        bool InintBird();
        bool ResetBird();
        bool SetFlyUp();
        bool SetFall();
        void GameStart();
        void GameOver();
        inline void setSize() {
            _width = this->boundingBox().size.width;
            _height = this->boundingBox().size.height;
        }
    private:
            void update(float dt);
            void flyactioncallback();
            float gravity;
    };
    #endif
    
    #include "Bird.h"
    static Cbird *instance = NULL;
    Cbird::Cbird()
    :_vector(ccp(0,0))
    ,_screenSize(CCDirector::sharedDirector()->getWinSize())
    ,gravity(2)
    {
        m_isfalling = false;
        m_state = playerRead;
    }
    
    Cbird::~Cbird()
    {
        CC_SAFE_RELEASE(m_flyAnimation);
        CC_SAFE_RELEASE(m_fallAnimation);
        CC_SAFE_RELEASE(m_NormalAnimation);
    }
    
    Cbird * Cbird::create( void )
    {
        Cbird * bird = new Cbird();
        if (bird && bird->initWithSpriteFrameName("bird_hero1.png")) {
            bird->autorelease();
            bird->setSize();
            bird->InintBird();
            instance = bird;
            return bird;
        }
        CC_SAFE_DELETE(bird);
        return NULL;
    }
    
    bool Cbird::InintBird()
    {
        //设置锚点
        this->setAnchorPoint(ccp(0.5f, 1.0f));
        this->setPosition(ccp(_screenSize.width * 0.36f,500/* _nextPosition.y*/));
    
        //_height = 228;
        //_width = 180;
        _height = 34;
        _width = 24;
        CCAnimation* animation;
        //创建一个空白的序列帧动画信息
        animation = CCAnimation::create();
    
        //CCSpriteFrame对应的就是帧,将CCSpriteFrame添加到CCAnimation生成动画数据,
        //用CCAnimation生成CCAnimate(就是最终的动画动作),最后可以用CCSprite执行这个动作。
        CCSpriteFrame * frame;
        int i;
        //共有3帧,这里用for循环将对应的序列图加入到动画中
        for(i = 1; i <= 3; i++) {
            char szName[100] = {0};
            sprintf(szName, "bird_hero%i.png", i);
            frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(szName);
            animation->addSpriteFrame(frame);
        }
    
        //设置每两帧间时间间隔
        animation->setDelayPerUnit(0.2f / 3.0f);
        //设置动画结束后是否保留动画帧信息
        animation->setRestoreOriginalFrame(false);
        //设置循环播放次数 (-1:无限循环)
        animation->setLoops(-1);
        //由这个动画信息创建一个序列帧动画
        m_NormalAnimation = CCAnimate::create(animation);
        //保存这个动画
        m_NormalAnimation->retain();
    
    
        this->runAction(m_NormalAnimation);
        m_fallAnimation = CCEaseOut::create(CCRotateTo::create(0.4f, 45), 0.4);
        m_fallAnimation->retain();
        this->runAction(m_fallAnimation);
        // update 
        //scheduleUpdate();
        this->schedule(schedule_selector(Cbird::update));
        return 1;
    }
    
    bool Cbird::SetFlyUp()
    {
        if (m_state == PlayerFlying)
        {
            this->stopAction(m_flyAnimation);
        }
        else if(m_fallAnimation)
            this->stopAction(m_fallAnimation);
        //CCAction *action1 = CCSpawn::create(
        //    CCMoveTo::create(0.25f,CCPointMake(this->getPositionX(),this->getPositionY()+30)),
        //    CCRotateTo::create(0.25f,-45),
        //    );
        //CCAction *action = CCSpawn::create(
        //    CCMoveTo::create(0.25f,CCPointMake(this->getPositionX(),this->getPositionY()+20)),
        //    CCRotateTo::create(0.25f,-45),
        //    NULL
        //    );
    
        //CCFiniteTimeAction *action = CCJumpTo::create(0.4f, CCPointMake(this->getPositionX(),this->getPositionY()),50,1);
    
        //CCAction *actions = CCSpawn::create(
        //    action,
        //    //CCRotateTo::create(0.25f,-45),
        //    CCSequence::create(
        //    CCEaseInOut::create(CCRotateTo::create(0.2f, 0), 2),
        //    CCEaseInOut::create(CCRotateTo::create(0.2f, 90), 2),
        //    NULL),
        //    NULL
        //    );
    
        //飞的动作
        if (m_state == playerRead||m_state == PlayerDying)
        {
            return 1;
        }
        gravity = 2;
        CCFiniteTimeAction *action = CCJumpTo::create(0.5f, CCPointMake(this->getPositionX(),this->getPositionY()+40),40,1);
    
        CCFiniteTimeAction *actionss = CCSpawn::create(
            action,
            //CCRotateTo::create(0.25f,-45),
            //CCSequence::create(
            CCSequence::actions(CCEaseIn::create(CCRotateTo::create(0.25f, -45), 0.4),CCEaseOut::create(CCRotateTo::create(0.25f, 0), 0.4),NULL),
        /*    CCCallFunc::create(this,callfunc_selector(Cbird::flyactioncallback)),  */
            //CCEaseInOut::create(CCRotateTo::create(0.2f, 90), 2),
            //NULL),
            NULL
            );
        CCFiniteTimeAction *actionin = CCEaseIn::create((CCActionInterval*)(actionss->copy()->autorelease()),0.5f);
    
        m_flyAnimation = CCSequence::create(  
            actionin,
            CCCallFunc::create(this,callfunc_selector(Cbird::flyactioncallback)), 
            NULL  
            );  
        m_flyAnimation->retain();
        this->runAction(m_flyAnimation);
        m_state = PlayerFlying;
        return 1;
    }
    
    void Cbird::update(float dt)
    {
        CCSize winSize = CCDirector::sharedDirector()->getWinSize();
        switch (m_state)
        {
        case PlayerFalling:
            // update bird positionY
            if (this->getPositionY() > 0 && this->getPositionY() < winSize.height)
            {
                //velocity -= gravity;
    
                this->setPositionY(this->getPositionY() -gravity);
                gravity += 0.3;
            }
            break;
        case PlayerDying:
            // update bird positionY
            if (this->getPositionY() > 0 && this->getPositionY() < winSize.height)
            {
                //velocity -= gravity;
                this->setPositionY(this->getPositionY() -gravity);
                gravity += 0.3;
            }
            break;
        case PlayerFlying:break;
        default:break;
        }
    }
    
    void Cbird::flyactioncallback()
    {
        /*Cbird::ShareBird()->*/m_state = PlayerFalling;
        this->stopAction(m_flyAnimation);
        //m_fallAnimation = CCEaseIn::create(CCRotateTo::create(0.4f, 90), 2);
        //m_fallAnimation->retain();
        this->runAction(m_fallAnimation);
    }
    
    Cbird * Cbird::ShareBird( void )
    {
        return instance;
    }
    
    void Cbird::GameStart()
    {
        m_state = PlayerFalling;
    }
    
    void Cbird::GameOver()
    {
        m_state = PlayerDying;
    }
    
    bool Cbird::ResetBird()
    {
        this->setPosition(ccp(_screenSize.width * 0.36f,500/* _nextPosition.y*/));
        gravity = 2;
        return 1;
    }

    源码地址:Download

  • 相关阅读:
    yii2 gii 命令行自动生成控制器和模型
    控制器中的方法命名规范
    Vue Property or method "" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based
    IDEA插件:GsonFormat
    Spring Boot : Access denied for user ''@'localhost' (using password: NO)
    Typora添加主题
    Git基础命令图解
    Java Joda-Time 处理时间工具类(JDK1.7以上)
    Java日期工具类(基于JDK1.7版本)
    Oracle SQL Developer 连接Oracle出现【 状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied】
  • 原文地址:https://www.cnblogs.com/shit/p/3579392.html
Copyright © 2011-2022 走看看