您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x开发日志10 ——贪食蛇源码

2015-08-18 20:01 525 查看
简单的游戏开发,比较适合和我一样的小白练手,除了游戏结束场景,全部包含在了HelloWorldScene中,先上源码,注释已经比较全面,但是具体细节会陆续更新。

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "GameOverScene.h"
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
using namespace cocos2d;
using namespace std;
//贪食蛇移动方向
typedef enum{
UP=1,
DOWN,
LEFT,
RIGHT
}DIR_DEF;

//蛇的头 身体 食物 共用这个node
class SnakeNode:public Node{
public:
int row; //行
int col; //列
int dir; //方向
DrawNode *pic;//要加载的图片
};

//欢迎场景
class HelloWorld : public Layer{
public:
virtual bool init();//初始化函数
static Scene * createScene();//获取欢迎画面的scene
void menuCloseCallback(Ref * pSender);
CREATE_FUNC(HelloWorld);

};

//帮助画面
class GameHelp: public Layer{
public:
virtual bool init();
static Scene * createScene();
CREATE_FUNC(GameHelp);
void menuBackToMain(Ref * pSender);
};

//游戏画面
class GameLayer : public Layer{
protected:
bool pause_resume=0;//是否暂停 0为继续,1为暂停
SnakeNode  *sHead;//贪食蛇的头部
SnakeNode  *sFood;//食物
Vector <SnakeNode*>  allbody;//身体
//暂存起点坐标 网格单位长度
int ox = 50;
int oy = 60;
int unit =20;
//获得分数
int score = 0;
public:
//初始化
virtual bool init();
static Scene * createScene();
CREATE_FUNC(GameLayer);
//游戏逻辑
void logic01(float t);
void menuBackToMain( Ref * pSender);//返回主菜单
};

#endif // __HELLOWORLD_SCENE_H__


HelloWorldScene.cpp

#include "HelloWorldScene.h"
#define START_TAG 10
#define HELP_TAG 11
#define EXIT_TAG 12
#define MAINMENU_TAG 13
#define UP_TAG 14
#define DOWN_TAG 15
#define LEFT_TAG 16
#define RIGHT_TAG 17
#define PAUSE_TAG 18
#define SCORE_TAG 19
#define MENU_TAG 20

USING_NS_CC;
using namespace cocos2d;

//************************************************************************//
//**                                                                    **//
//**                              欢迎界面                               **//
//**                                                                    **//
//************************************************************************//

//欢迎界面方法
Scene * HelloWorld::createScene(){
Scene * scene = Scene::create();
HelloWorld * layer = HelloWorld::create();
scene-> addChild(layer);
return scene;
}

//欢迎界面初始化方法
bool HelloWorld::init(){
if (!Layer::init())
return false;

//游戏名称标签
auto label = Label::createWithTTF("SNAKE", "fonts/Marker Felt.ttf", 50);
label->setColor(Color3B(0,120,100));
label->setPosition(Director::getInstance()->getWinSize().width/2,
Director::getInstance()->getWinSize().height/2+
label->getContentSize().height*1.5);
this->addChild(label);

//开始 按钮
auto start = Label::createWithTTF("Start Game", "fonts/Marker Felt.ttf", 24);
start->setColor(Color3B(0,255,0));
auto start_button = MenuItemLabel::create(start,CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
start_button->setPositionY(start->getPositionY()+start_button->getContentSize().height*1.5);
start_button->setTag(START_TAG);
//帮助 按钮
auto help = Label::createWithTTF("Help", "fonts/Marker Felt.ttf", 24);
help->setColor(Color3B(0,0,255));
auto help_button = MenuItemLabel::create(help,CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
help_button->setTag(HELP_TAG);
//退出 按钮
auto exit = Label::createWithTTF("Exit", "fonts/Marker Felt.ttf", 24);
exit->setColor(Color3B(200,0,200));
auto exit_button = MenuItemLabel::create(exit,CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
exit_button->setPositionY(start->getPositionY()-exit_button->getContentSize().height*1.5);
exit_button->setTag(EXIT_TAG);
//新建菜单
auto menu = Menu::create(start_button,help_button,exit_button,NULL);
this->addChild(menu);

return true;
}

//欢迎界面菜单回调函数
void HelloWorld::menuCloseCallback(Ref * pSender){
switch (((MenuItemLabel*)pSender)->getTag()) {
case START_TAG:{
auto scene = GameLayer::createScene();
Director::getInstance()->replaceScene(scene);
break;
}

case HELP_TAG:{
auto scene = GameHelp::createScene();
Director::getInstance()->replaceScene(scene);
break;
}

case EXIT_TAG:
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
break;

default:
break;
}
}

//************************************************************************//
//**                                                                    **//
//**                              帮助界面                                **//
//**                                                                    **//
//************************************************************************//

//帮助画面方法
Scene * GameHelp::createScene(){
auto scene = Scene::create();
auto layer = GameHelp::create();
scene-> addChild(layer);
return scene;
}

//帮助画面初始化方法
bool GameHelp::init(){
if (!Layer::init())
return false;

//帮助文字
auto label = Label::createWithTTF("DO NOT TELL ME YOU CAN'T DO THIS ,YOU FOOL!", "fonts/Marker Felt.ttf", 24);
label->setColor(Color3B(200,70,200));
label->setPosition(Director::getInstance()->getWinSize().width/2,
Director::getInstance()->getWinSize().height/2+50);
this->addChild(label);

//返回主菜单 按钮
auto MainMenu = Label::createWithTTF("Main Menu", "fonts/Marker Felt.ttf", 24);
MainMenu->setColor(Color3B(0,200,200));
auto MainMenu_button = MenuItemLabel::create(MainMenu,CC_CALLBACK_1(GameHelp::menuBackToMain, this));
MainMenu_button->setPositionY(MainMenu_button->getPositionY()-50);
MainMenu_button->setTag(EXIT_TAG);
//新建菜单
auto menu = Menu::create(MainMenu_button,NULL);
this->addChild(menu);

return true;
}

//帮助画面菜单回调方法
void GameHelp::menuBackToMain(Ref * pSender){
auto scene = HelloWorld::createScene();
Director::getInstance()->replaceScene(scene);
}

//************************************************************************//
//**                                                                    **//
//**                              游戏界面                                **//
//**                                                                    **//
//************************************************************************//

//游戏界面方法
Scene * GameLayer:: createScene(){
auto scene = Scene::create();
auto layer = GameLayer::create();
scene->addChild(layer);
return scene;
}

bool GameLayer::init(){
if (!Layer::init())
return false;

//返回主菜单 按键
auto MainMenu = Label::createWithTTF("Main Menu", "fonts/Marker Felt.ttf", 24);
MainMenu->setColor(Color3B(0,200,200));
auto MainMenu_button = MenuItemLabel::create(MainMenu,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
MainMenu_button->setTag(0);
MainMenu_button->setPosition(Director::getInstance()->getWinSize().width*0.3,
-Director::getInstance()->getWinSize().height*0.3);
//暂停 按键
auto pause = Label::createWithTTF("PAUSE", "fonts/Marker Felt.ttf", 24);
pause->setColor(Color3B(255,100,100));
auto pause_button = MenuItemLabel::create(pause,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
pause_button->setTag(PAUSE_TAG);
pause_button->setPosition(Director::getInstance()->getWinSize().width*0.3,
-Director::getInstance()->getWinSize().height*0.3+140);
//向上 按键
auto up = Label::createWithTTF("UP", "fonts/Marker Felt.ttf", 24);
up->setColor(Color3B(0,255,0));
auto up_button = MenuItemLabel::create(up,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
up_button->setTag(UP_TAG);
up_button->setPosition(Director::getInstance()->getWinSize().width*0.3,
-Director::getInstance()->getWinSize().height*0.3+100);

//向下 按键
auto down = Label::createWithTTF("DOWN", "fonts/Marker Felt.ttf", 24);
down->setColor(Color3B(0,255,0));
auto down_button = MenuItemLabel::create(down,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
down_button->setTag(DOWN_TAG);
down_button->setPosition(Director::getInstance()->getWinSize().width*0.3,
-Director::getInstance()->getWinSize().height*0.3+40);

//向左 按键
auto left = Label::createWithTTF("LEFT", "fonts/Marker Felt.ttf", 24);
left->setColor(Color3B(0,255,0));
auto left_button = MenuItemLabel::create(left,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
left_button->setTag(LEFT_TAG);
left_button->setPosition(Director::getInstance()->getWinSize().width*0.3-30,
-Director::getInstance()->getWinSize().height*0.3+70);

//向右 按键
auto right = Label::createWithTTF("RIGHT", "fonts/Marker Felt.ttf", 24);
right->setColor(Color3B(0,255,0));
auto right_button = MenuItemLabel::create(right,CC_CALLBACK_1(GameLayer::menuBackToMain, this));
right_button->setTag(RIGHT_TAG);
right_button->setPosition(Director::getInstance()->getWinSize().width*0.3+30,
-Director::getInstance()->getWinSize().height*0.3+70);
//新建菜单
auto menu = Menu::create(MainMenu_button,up_button,left_button,down_button,right_button,pause_button,NULL);
this->addChild(menu);
menu->setTag(MENU_TAG);

//显示分数
char a[3] ;
stringstream stream;
stream << score;
stream >> a;
auto score_label = Label::createWithTTF (a, "fonts/Marker Felt.ttf", 40);
score_label->setPosition(Director::getInstance()->getWinSize().width*0.8,
Director::getInstance()->getWinSize().height*0.8);
score_label->setTag(SCORE_TAG);
this->addChild(score_label);

//设置网格
for(int i=0; i<11; i++){
for(int j=0; j<11 ;j++){
auto head1 = DrawNode::create();
head1->drawDot(Point(0,0), 1, Color4F(1, 1, 1, 0.5));
head1->setPosition(Vec2(ox+unit*i, oy+unit*j));
this->addChild(head1,4);
}
}

//初始化蛇头
sHead = new SnakeNode();
sHead->row = arc4random()%10;
sHead->col = arc4random()%10;
sHead->dir = arc4random()%4+1;
CCLOG("%d %d",sHead->row,sHead->col);
sHead->pic = DrawNode::create();
sHead->pic->drawSolidRect(Point(0,0),Point(unit,unit),Color4F(1, 0, 0, 0.8));
sHead->pic->setPosition(Vec2(ox+sHead->col*unit,oy+sHead->row*unit));
this->addChild(sHead->pic,2);

//初始化食物
sFood = new SnakeNode;
sFood->row = arc4random()%10;
sFood->col = arc4random()%10;
sFood->pic = DrawNode::create();
sFood->pic->drawSolidRect(Point(0,0),Point(unit,unit), Color4F(1,1,1,1));
sFood->pic->setPosition(Vec2(ox+sFood->col*unit,oy+sFood->row*unit));
this->addChild(sFood->pic,2);

//初始化身体
//allbody.reserve(1);
//执行计划任务
this->schedule(schedule_selector(GameLayer::logic01), 0.8);
return true;
}

//游戏界面菜单回调方法
void GameLayer::menuBackToMain( Ref * pSender){
auto p = (MenuItemLabel*)pSender;
switch (p->getTag()) {
case 0:{
auto scene = HelloWorld::createScene();
Director::getInstance()->replaceScene(scene);
break;
}

case UP_TAG:{
if(sHead->dir!=DIR_DEF::DOWN)
sHead->dir = DIR_DEF::UP;
break;
}

case DOWN_TAG:{
if(sHead->dir!=DIR_DEF::UP)
sHead->dir = DIR_DEF::DOWN;
break;
}

case LEFT_TAG:{
if(sHead->dir!=DIR_DEF::RIGHT)
sHead->dir = DIR_DEF::LEFT;
break;
}

case RIGHT_TAG:{
if(sHead->dir!=DIR_DEF::LEFT)
sHead->dir = DIR_DEF::RIGHT;
break;
}

case PAUSE_TAG:{
if(pause_resume == 0){
pause_resume = 1;
unschedule(schedule_selector(GameLayer::logic01));
MenuItemLabel* l = (MenuItemLabel*)this->getChildByTag(MENU_TAG)-> getChildByTag(PAUSE_TAG);
l->setString("RESUME");
}
else{
//Director::getInstance()->resume();
pause_resume = 0;
schedule(schedule_selector(GameLayer::logic01), 0.8);
MenuItemLabel * l = (MenuItemLabel*)this->getChildByTag(MENU_TAG)->getChildByTag(PAUSE_TAG);
l->setString("PAUSE");
}
break;
}
default:
break;
}
}

//计划任务
void GameLayer::logic01(float t){

//移动身体
for (int i = allbody.size()-1; i>=0; i--) {
SnakeNode * sn = allbody.at(i);
if (i>0) {
auto snpre = allbody.at(i-1);
sn->dir = snpre->dir;
sn->row = snpre->row;
sn->col = snpre->col;
}
//移动第一个节点
else if (i==0) {
sn->dir = sHead->dir;
sn->row = sHead->row;
sn->col = sHead->col;

}
}

//移动蛇头
switch (sHead->dir) {
case DIR_DEF::UP:{
sHead->row++;
if(sHead->row >= 10)
sHead->row = 0;
break;
}

case DIR_DEF::DOWN:{
sHead->row--;
if(sHead->row < 0)
sHead->row = 9;
break;
}

case DIR_DEF::LEFT:{
sHead->col--;
if(sHead->col < 0)
sHead->col = 9;
break;
}

case DIR_DEF::RIGHT:{
sHead->col++;
if(sHead->col >= 10)
sHead->col = 0;
break;
}

}

//头结点重置图像位置
sHead->pic->setPosition(Vec2(ox+sHead->col*unit,oy+sHead->row*unit));

//碰撞检测
if(sHead->row==sFood->row && sHead->col==sFood->col){
score ++;
char a[3] ;
stringstream stream;
stream << score;
stream >> a;
auto l =(Label *)this->getChildByTag(SCORE_TAG);
l->setString(a);

//食物消失
while(1){
bool flag = true;
sFood->row = rand()%10;
sFood->col = rand()%10;
for (int i=0; i<allbody.size(); i++) {
if(allbody.at(i)->row==sFood->row && allbody.at(i)->col==sFood->col)
flag = false;
}
if(flag == true) break;
}
sFood->pic->setPosition(Vec2(ox+sFood->col*unit,oy+sFood->row*unit));
//添加身体到集合
SnakeNode  * sn;
sn = new SnakeNode;
SnakeNode  *lastNode;
if (allbody.size()>0)
lastNode = allbody.at(allbody.size()-1);
else
lastNode = sHead;
switch (lastNode->dir) {
case DIR_DEF::UP:
sn->row = lastNode->row-1;
sn->col = lastNode->col;
break;

case DIR_DEF::DOWN:
sn->row = lastNode->row+1;
sn->col = lastNode->col;
break;

case DIR_DEF::LEFT:
sn->row = lastNode->row;
sn->col = lastNode->col+1;
break;

case DIR_DEF::RIGHT:
sn->row = lastNode->row;
sn->col = lastNode->col-1;
break;
}
sn->dir = lastNode->dir;
this->allbody.pushBack(sn);
sn->pic = DrawNode::create();
sn->pic->drawSolidRect(Point(0,0),Point(unit,unit),Color4F(0, 1, 0, 0.8));
sn->pic->setPosition(Vec2(ox+sn->col*unit,oy+sn->row*unit));
this->addChild(sn->pic);

}
//重置身体位置
for (int i = 0; i<allbody.size(); i++) {
allbody.at(i)->pic->setPosition(Vec2(ox+allbody.at(i)->col*unit,oy+allbody.at(i)->row*unit));
}

//game over 判定
for (int i=0; i<allbody.size(); i++)
if(allbody.at(i)->row==sHead->row && allbody.at(i)->col==sHead->col){
auto scene = GameOver::createScene();
Director::getInstance()->replaceScene(scene);
}
}


GameOverScene.h

//
//  GameOverScene.h
//  snakegame
//
//  Created by jiumiao on 15/8/9.
//
//

#ifndef __snakegame__GameOverScene__
#define __snakegame__GameOverScene__

#include <stdio.h>
#include "cocos2d.h"
#include "HelloWorldScene.h"
USING_NS_CC;

class GameOver : public Layer{
public:
bool init();//初始化函数
static Scene * createScene();//获取欢迎画面的scene
void menuCloseCallback(Ref * pSender);
CREATE_FUNC(GameOver);

};

#endif /* defined(__snakegame__GameOverScene__) */


GameOverScene.cpp

//
//  GameOverScene.cpp
//  snakegame
//
//  Created by jiumiao on 15/8/9.
//
//

#include "GameOverScene.h"

//初始化函数
bool GameOver:: init(){
if(!Layer::init())
return false;
//Game Over
auto label = Label::createWithTTF("Game Over", "fonts/Marker Felt.ttf", 50);
label->setColor(Color3B(255,120,100));
label->setPosition(Director::getInstance()->getWinSize().width/2,
Director::getInstance()->getWinSize().height/2+
label->getContentSize().height*1.5);
this->addChild(label);

//返回游戏 按钮
auto tryagain = Label::createWithTTF("Try Again", "fonts/Marker Felt.ttf", 24);
tryagain->setColor(Color3B(0,200,200));
auto tryagain_button = MenuItemLabel::create(tryagain,CC_CALLBACK_1(GameOver::menuCloseCallback, this));
tryagain_button->setPositionY(tryagain_button->getPositionY()-50);
tryagain_button->setTag(20);
auto menu = Menu::create(tryagain_button,NULL);
this->addChild(menu);

return true;
}

//获取结束画面
Scene * GameOver::createScene(){
auto scene = Scene::create();
auto layer = GameOver::create();
scene-> addChild(layer);
return scene;
}

void GameOver::menuCloseCallback(Ref * pSender){
auto scene = GameLayer::createScene();
Director::getInstance()->replaceScene(scene);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: