1. 程式人生 > >Cocos2d-x 3.0final 終結者系列教程13-貪食蛇遊戲案例(全)

Cocos2d-x 3.0final 終結者系列教程13-貪食蛇遊戲案例(全)

track print return pla sprint 宋體 能夠 post world

快過節了。謝謝了屈原,我們愛你。

應該多幾個向屈大人一樣跳江的,這樣我們就能夠放假紀念啦。

---------------------------------快過節了。弄個案例,大家最好還是假期做做,

執行效果展示:

技術分享圖片

技術分享圖片

所有代碼和資源:

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;

}

--------------------------------------------祝你成功-----------------------

Cocos2d-x 3.0final 終結者系列教程13-貪食蛇遊戲案例(全)