• 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

  • 相关阅读:
    PLSQL_Oracle Trigger触发器的基本概念和用法
    PLSQL_Oracle Object所有数据库对象类型汇总和简解(概念)
    OAF_EO系列2
    OAF_EO系列1
    OAF_OAF Debug And Log调试和记录工具的详解(案例)
    OAF_OAF Exception Handling异常处理(概念)
    DBA_FND Load程式迁移工具介绍和应用(案例)
    Form_Form标准控件Folder开发解析(案列)
    BEvent_标准BusinessEvent用以监控供应商的修改(案例)
    PLSQL_Oracle Logon Trigger的建立
  • 原文地址:https://www.cnblogs.com/shit/p/3579392.html
Copyright © 2020-2023  润新知