zoukankan      html  css  js  c++  java
  • Cocos2d-x 3.0final 终结者系列教程13-贪食蛇游戏案例(全)

    快过节了。谢谢了屈原,我们爱你。

    应该多几个向屈大人一样跳江的,这样我们就能够放假纪念啦。

    ---------------------------------快过节了。弄个案例,大家最好还是假期做做,

    执行效果展示:



    所有代码和资源:

    http://download.csdn.net/detail/sdhjob/7424329

    1.准备资源

    背景图片menuback.png:


    节点图片

    greenstar.png   

    redstar.png      

    yellowstar.png 

    2.创建一个新项目(怎样配置环境和创建新项目,參考前面教程):

    cocos new -p com.xdl.game -l cpp -d ~/Desktop/test0515 snamegame

    3.加入文件

    首先将HelloWoldScene.h HelloWorld.cpp移走。然后加入GameScene.h GameScene.cpp HelpScene.h HelpScene.cpp MainMenu.h MainMenu.cpp

    加上原来自己主动生成的AppDelegate.h 和AppDelegate.cpp共8个文件

    4.编码

    AppDelegate.h (这个文件基本没修改)

    #ifndef  _APP_DELEGATE_H_

    #define  _APP_DELEGATE_H_

    #include "cocos2d.h"

    class  AppDelegate : private cocos2d::Application

    {

    public:

        AppDelegate();

        virtual ~AppDelegate();

        virtual bool applicationDidFinishLaunching();

        virtual void applicationDidEnterBackground();

        virtual void applicationWillEnterForeground();

    };

    #endif // _APP_DELEGATE_H_

    AppDelegate.cpp 

    #include "AppDelegate.h"

    #include "MainMenu.h"

    #include "SimpleAudioEngine.h"    

    USING_NS_CC;

    using namespace CocosDenshion;

    AppDelegate::AppDelegate() {

    }

    AppDelegate::~AppDelegate() 

    {

    }

    bool AppDelegate::applicationDidFinishLaunching() {

        // initialize director

        auto director = Director::getInstance();

        auto glview = director->getOpenGLView();

        if(!glview) {

            glview = GLView::create("My Game");

            director->setOpenGLView(glview);

        }

        // turn on display FPS

        director->setDisplayStats(false);

        // set FPS. the default value is 1.0/60 if you don't call this

        director->setAnimationInterval(1.0 / 60);

        // create a scene. it's an autorelease object

        auto scene = MainMenu::createScene();

        // run

        director->runWithScene(scene);

        //開始播放背景音乐

        SimpleAudioEngine::getInstance()->playBackgroundMusic("background.mp3");

        return true;

    }


    // This function will be called when the app is inactive. When comes a phone call,it's be invoked too

    void AppDelegate::applicationDidEnterBackground() {

        Director::getInstance()->stopAnimation();

        // if you use SimpleAudioEngine, it must be pause

        SimpleAudioEngine::getInstance()->pauseBackgroundMusic();

    }


    // this function will be called when the app is active again

    void AppDelegate::applicationWillEnterForeground() {

        Director::getInstance()->startAnimation();

        // if you use SimpleAudioEngine, it must resume here

        SimpleAudioEngine::getInstance()->resumeBackgroundMusic();

    }

    说明: 在入口类中增加了背景音乐的播放,而且入口场景设计为MainMenu,往下看

    MainMenu.h

    #ifndef __snakegame__MainMenu__

    #define __snakegame__MainMenu__

    #include "cocos2d.h"

    USING_NS_CC;

    class MainMenu:public Layer{

    public:

        static Scene * createScene();

        CREATE_FUNC(MainMenu);

        virtual bool init();

        void menuCallBack(Ref * object);

    };

    #endif


    MainMenu.cpp

    #include "MainMenu.h"

    #include "GameScene.h"

    #include "HelpScene.h"

    Scene * MainMenu::createScene()

    {   auto scene=Scene::create();

        auto layer=MainMenu::create();

        scene->addChild(layer);

        return scene;

    }

     bool MainMenu::init(){

         if(!Layer::init())

        {

        return false;

        }

         auto size=Director::getInstance()->getWinSize();

         //加入背景

         auto spriteBK=Sprite::create("menuback.png");

         spriteBK->setPosition(Point(size.width/2,size.height/2));

         this->addChild(spriteBK);

         //加入2个菜单栏目

         auto menuItemStart=MenuItemFont::create("Start", CC_CALLBACK_1(MainMenu::menuCallBack,this));

         menuItemStart->setTag(1);

         auto menuItemHelp=MenuItemFont::create("Help", CC_CALLBACK_1(MainMenu::menuCallBack,this));

         menuItemHelp->setTag(2);

         auto menu=Menu::create(menuItemStart,menuItemHelp,NULL);

         menu->setPosition(Point::ZERO);

         menuItemStart->setPosition(Point(size.width-menuItemStart->getContentSize().width-100,menuItemStart->getContentSize().height+10));

         menuItemHelp->setPosition(Point(size.width-menuItemHelp->getContentSize().width-10,menuItemHelp->getContentSize().height+10));

         this->addChild(menu);

         return true;

    }

    void MainMenu::menuCallBack(Ref * object){

        auto target=(Node *)object;

        Scene * scene;

        switch (target->getTag()) {

            case 1://startgame

                scene=Game::createScene();

                break;

            case 2://Helpgame

                scene=Help::createScene();

                break;

            default:

                break;

        }

        Director::getInstance()->replaceScene(scene);

      }

    说明:在菜单场景中实现了跳转到帮助场景和游戏场景,往下看:

    HelpScene.h

    #ifndef __snakegame__HelpScene__

    #define __snakegame__HelpScene__

    #include "cocos2d.h"

    USING_NS_CC;

    class Help:public Layer{

    public:

        static Scene * createScene();

        CREATE_FUNC(Help);

        virtual bool init();

        void menuCallBack(Ref * object);

    };

    #endif

    HelpScene.cpp

    #include "HelpScene.h"

    #include "MainMenu.h"

    Scene * Help::createScene(){

        auto scene=Scene::create();

        auto layer=Help::create();

        scene->addChild(layer);

        return scene;

       }

    bool  Help::init(){

        if(!Layer::init())

            {

            return  false;

            }

          auto size=Director::getInstance()->getWinSize();

        //加入背景

        auto spriteBK=Sprite::create("menuback.png");

        spriteBK->setPosition(Point(size.width/2,size.height/2));

        spriteBK->setOpacity(75);

        this->addChild(spriteBK);

        //帮助信息

        auto labelScore=Label::create("帮助信息", "宋体", 25);

        labelScore->setPosition(Point(size.width-80,size.height-50));

        this->addChild(labelScore);

        //返回button

        auto menuItemBack=MenuItemFont::create("Back", CC_CALLBACK_1(Help::menuCallBack,this));

        auto menu=Menu::create(menuItemBack,NULL);

        menu->setPosition(Point::ZERO);

        menuItemBack->setPosition(Point(size.width-menuItemBack->getContentSize().width-100,menuItemBack->getContentSize().height+10));

        this->addChild(menu);

        return true;

    }

    void  Help::menuCallBack(Ref * object){

        auto scene=MainMenu::createScene();

        Director::getInstance()->replaceScene(scene);

    }

    说明:这里仅仅是实现了一个帮助信息显示。能够返回到菜单。以下看游戏场景

    GameScene.h

    #ifndef __snakegame__GameScene__

    #define __snakegame__GameScene__

    #include "cocos2d.h"

    USING_NS_CC;

    enum class ENUM_DIR{

        DIR_UP,

        DIR_DOWN,

        DIR_LEFT,

        DIR_RIGHT,

        DIR_STOP

    };

    class SnakeNode:public Sprite

    {

        public :

        enum ENUM_DIR m_dir;//移动方向

        int nodeType;       //节点类型1蛇头 2 身体 3 食物

        int m_row,m_col;    //当前节点的行列坐标

       

        static SnakeNode* create(int type);

        virtual bool init(int type);

        void setPositionRC(int row,int col);//设置节点的坐标

    };

    class Game:public Layer{

    public:

        SnakeNode * spFood;//食物

        SnakeNode * spHead;//蛇头

         int m_score;

        Vector<SnakeNode *> allBody;//身体

        static Scene * createScene();

        CREATE_FUNC(Game);

        virtual bool init();

        void menuCallBack(Ref * object);

        void gameLogic(float t);

        void newBody();//加入一个新的身体节点

        void moveBody();//移动全部的身体节点

    };

    #endif

    GameScene.cpp

    //

    //  GameScene.cpp

    //  Created by shen on 14-5-27.

    //


    #include "GameScene.h"

    #include "MainMenu.h"

    #include "SimpleAudioEngine.h"

    using namespace CocosDenshion;

    Scene * Game::createScene(){

        auto scene=Scene::create();

        auto layer=Game::create();

        scene->addChild(layer);

        return scene;


    }

    SnakeNode* SnakeNode::create(int type)

    {

        SnakeNode *pRet = new SnakeNode();

        if (pRet && pRet->init(type))

            {

                pRet->autorelease();

                return pRet;

            }

        else

            {

                delete pRet;

                pRet = NULL;

                return NULL;

            }

    }


    bool SnakeNode::init(int type){

        if(!Sprite::init())

        {

         return false;

        }

        ///依据类型不同初始化不同的纹理

        switch (type) {

            case 1://蛇头

            {auto sprite=Sprite::create("redstar.png");

                sprite->setAnchorPoint(Point::ZERO);

                this->addChild(sprite);

                m_dir=ENUM_DIR::DIR_RIGHT;//向右移动

            }

                break;

            case 2://身体

            {auto sprite=Sprite::create("greenstar.png");

                sprite->setAnchorPoint(Point::ZERO);

                this->addChild(sprite);

               

            }

                m_dir=ENUM_DIR::DIR_STOP;//

                break;

            case 3://食物

            {auto sprite=Sprite::create("yellowstar.png");

                sprite->setAnchorPoint(Point::ZERO);

                this->addChild(sprite);

            }

                 m_dir=ENUM_DIR::DIR_STOP;//

                break;

            default:

                break;

        }

        return true;

    }

    void SnakeNode::setPositionRC(int row,int col)//设置节点的坐标

    {    this->m_row=row;

         this->m_col=col;

          setPosition(Point(col*32,row*32));

    }

    bool  Game::init(){

        if(!Layer::init())

        {

        return  false;

        }

        //加入地图

        auto draw=DrawNode::create();

        draw->setAnchorPoint(Point::ZERO);

        draw->setPosition(Point::ZERO);

        this->addChild(draw);

        for(int i=0;i<11;i++)

        {

        draw->drawSegment(Point(0,32*i), Point(320,32*i), 1, Color4F(1,1,1,1));

        draw->drawSegment(Point(32*i,0), Point(32*i,320), 1, Color4F(1,1,1,1));

        }

        //加入蛇头

        spHead=SnakeNode::create(1);

        

        

        this->addChild(spHead);

        //加入身体

        //加入食物

         spFood=SnakeNode::create(3);

     

        int row=rand()%10;

        int col=rand()%10;

        spFood->setPositionRC(row,col);

        this->addChild(spFood);

        auto size=Director::getInstance()->getWinSize();

        //加入背景

        auto spriteBK=Sprite::create("menuback.png");

        spriteBK->setPosition(Point(size.width/2,size.height/2));

        spriteBK->setOpacity(75);

        this->addChild(spriteBK);

        //分数显示

        m_score=0;

        auto labelScore=Label::create("分数:0", "宋体", 25);

        labelScore->setTag(110);

        labelScore->setPosition(Point(size.width-80,size.height-50));

        this->addChild(labelScore);

        //返回button

        auto menuItemBack=MenuItemFont::create("Back", CC_CALLBACK_1(Game::menuCallBack,this));

        auto menu=Menu::create(menuItemBack,NULL);

        menu->setPosition(Point::ZERO);

        menuItemBack->setPosition(Point(size.width-menuItemBack->getContentSize().width-50,menuItemBack->getContentSize().height+10));

        this->addChild(menu);

         //计划任务

        this->schedule(schedule_selector(Game::gameLogic),0.5);

        //增加用户触摸事件侦听

        auto listener=EventListenerTouchOneByOne::create();

        listener->setSwallowTouches(true);

        listener->onTouchBegan=[&](Touch * t,Event * e){

            //改变贪食蛇移动的方向

            int col=t->getLocation().x/32;

            int row=t->getLocation().y/32;

            int spHeadCol=spHead->getPositionX()/32;

            int spHeadRow=spHead->getPositionY()/32;

            if(abs(spHeadCol-col)>abs(spHeadRow-row))

            {

               if(spHeadCol<col)

                {

                spHead->m_dir=ENUM_DIR::DIR_RIGHT;

                }else

                {

                    spHead->m_dir=ENUM_DIR::DIR_LEFT;

                }

            }

            else

                {if(spHeadRow<row)

                    {

                    spHead->m_dir=ENUM_DIR::DIR_UP;

                    }else

                        {

                        spHead->m_dir=ENUM_DIR::DIR_DOWN;

                        }

            

            }

            

            return true;

        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

        return true;

    }

    void  Game::menuCallBack(Ref * object){

        auto scene=MainMenu::createScene();

        Director::getInstance()->replaceScene(scene);

    }

    void Game::gameLogic(float t)

    {   moveBody();//移动全部身体节点

        //蛇头移动

        switch (spHead->m_dir) {

            case ENUM_DIR::DIR_RIGHT:

                spHead->runAction(MoveBy::create(0.3, Point(32,0)));

                spHead->m_col++;

                break;

            case ENUM_DIR::DIR_LEFT:

                spHead->runAction(MoveBy::create(0.3, Point(-32,0)));

                spHead->m_col--;

                break;

            case ENUM_DIR::DIR_DOWN:

                spHead->runAction(MoveBy::create(0.3, Point(0,-32)));

                spHead->m_row--;

                break;

            case ENUM_DIR::DIR_UP:

                spHead->runAction(MoveBy::create(0.3, Point(0,32)));

                spHead->m_row++;

                break;

       

            default:

                break;

        }

        //碰撞检測

        if(spHead->m_row==spFood->m_row&&

           spHead->m_col==spFood->m_col)

        {  //音效的播放

            SimpleAudioEngine::getInstance()->playEffect("eat.wav");

            //分数添加

            this->m_score+=100;

            Label * label=(Label *)this->getChildByTag(110);

            char strscore[20];

            sprintf(strscore, "分数:%d",m_score);

            label->setString(strscore);

          //食物产生新的位置

            int row=rand()%10;

            int col=rand()%10;

            spFood->setPositionRC(row,col);

          //加入节点

            newBody();

        }

    }

    void Game::newBody()//加入一个新的身体节点

    {

        auto bodynode=SnakeNode::create(2);

        //设置这个节点的方向和坐标

        if(allBody.size()>0)//有身体节点

        { //最后一个身体的节点

             auto lastbody=allBody.at(allBody.size()-1);

          bodynode->m_dir=lastbody->m_dir;

           

            switch (bodynode->m_dir) {

                case ENUM_DIR::DIR_UP:

                    bodynode->setPositionRC(lastbody->m_row-1, lastbody->m_col);

                    break;

                case ENUM_DIR::DIR_DOWN:

                    bodynode->setPositionRC(lastbody->m_row+1, lastbody->m_col);

                    break;

                case ENUM_DIR::DIR_LEFT:

                    bodynode->setPositionRC(lastbody->m_row, lastbody->m_col+1);

                    break;

                case ENUM_DIR::DIR_RIGHT:

                    bodynode->setPositionRC(lastbody->m_row, lastbody->m_col-1);

                    break;

                default:

                    break;

            }


        }else

        { //新节点的方向等于蛇头的方向

            bodynode->m_dir=spHead->m_dir;

            switch (bodynode->m_dir) {

                case ENUM_DIR::DIR_UP:

                    bodynode->setPositionRC(spHead->m_row-1, spHead->m_col);

                    break;

                case ENUM_DIR::DIR_DOWN:

                    bodynode->setPositionRC(spHead->m_row+1, spHead->m_col);

                    break;

                case ENUM_DIR::DIR_LEFT:

                    bodynode->setPositionRC(spHead->m_row, spHead->m_col+1);

                    break;

                case ENUM_DIR::DIR_RIGHT:

                    bodynode->setPositionRC(spHead->m_row, spHead->m_col-1);

                    break;

                default:

                    break;

            }

        }

        //加入节点到当前图层

        this->addChild(bodynode);

        //加入节点到集合中

        allBody.pushBack(bodynode);

    }

    void Game::moveBody()//移动全部的身体节点

    {

        if(allBody.size()==0){return;}

        for(auto bodynode:allBody)

        {

        switch (bodynode->m_dir) {

            case ENUM_DIR::DIR_RIGHT:

                bodynode->runAction(MoveBy::create(0.3, Point(32,0)));

                bodynode->m_col++;

                break;

            case ENUM_DIR::DIR_LEFT:

                bodynode->runAction(MoveBy::create(0.3, Point(-32,0)));

                bodynode->m_col--;

                break;

            case ENUM_DIR::DIR_DOWN:

                bodynode->runAction(MoveBy::create(0.3, Point(0,-32)));

                bodynode->m_row--;

                break;

            case ENUM_DIR::DIR_UP:

                bodynode->runAction(MoveBy::create(0.3, Point(0,32)));

                bodynode->m_row++;

                break;

            default:

                break;

            }

         }

        //移动完毕之后,改变每一个body的方向

        for(int i=allBody.size()-1;i>0;i--)

        { //每一个节点的 方向调整为它前一个节点的方向

            allBody.at(i)->m_dir=allBody.at(i-1)->m_dir;

        }

        allBody.at(0)->m_dir=spHead->m_dir;

    }

    --------------------------------------------祝你成功-----------------------
  • 相关阅读:
    我又来定计划了~2015-8至年底
    Spark官方文档中推荐的硬件配置
    java 多线程之:sleep() 方法
    Referrer Policy 介绍
    js 操作 cookie
    顶级域名和子级域名之间的cookie共享和相互修改、删除
    关于 Cookie-free Domains (为什么将静态图片,js,css存放到单独的域名?)
    cookie 知识点
    java 多线程之:yield() 方法
    java 多线程之:wait()、notify()、notifyAll()等方法
  • 原文地址:https://www.cnblogs.com/llguanli/p/8453504.html
Copyright © 2011-2022 走看看