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);

    //返回按鈕

    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);

    //返回按鈕

    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;

}

--------------------------------------------祝你成功-----------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章