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:publicLayer{ public: static Scene * createScene(); CREATE_FUNC(MainMenu); virtual bool init(); void menuCallBack(Ref * object); }; #endif
#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",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()) { case1://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:publicSprite { 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,1,Color4F(1,1)); draw->drawSegment(Point(32*i,0),Point(32*i,320),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,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,0))); bodynode->m_col++; break; case ENUM_DIR::DIR_LEFT: bodynode->runAction(MoveBy::create(0.3,0))); bodynode->m_col--; break; case ENUM_DIR::DIR_DOWN: bodynode->runAction(MoveBy::create(0.3,-32))); bodynode->m_row--; break; case ENUM_DIR::DIR_UP: bodynode->runAction(MoveBy::create(0.3,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; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |