现在就是最主要也是较为复杂的界面和逻辑类了。
他实际包含两个类,一个SnakeNode蛇结点类和一个Game界面逻辑类。
绘制10*10的网格,初始化一个食物和一个蛇头,随机的坐标,然后定时移动蛇头,碰到食物则吃掉并产生一个身体结点,碰撞检测,到边界就结束返回主界面。
GameScene.h:
#pragma execution_character_set("utf-8")
#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_DIR m_dir; //移动方向
int nodeType; //节点类型: 1蛇头 2 身体 3 食物
int m_row,m_col; //当前节点的行列坐标
public:
static SnakeNode* create(int type);//!!!
virtual bool init(int type);
void setPositionRC(int row,int col);//设置节点的坐标
};
class Game:public Layer
{
public:
//enum RESOLUTION{
// NET_SIZE = 64,
// NET_WIDTH = 640
// _WIDTH = 960,
// _HEIGHT = 640
//};
SnakeNode * spFood;//食物
SnakeNode * spHead;//蛇头
int m_score;
Vector<SnakeNode *> allBody;//身体!!!
static Scene * createScene();
CREATE_FUNC(Game);
virtual bool init();
public:
void menuCallBack(Ref * object);
void gameLogic(float t);
void newBody();//添加一个新的身体节点
void moveBody();//移动所有的身体节点
};
#endif /* defined(__snakegame__GameScene__) */
GameScen.cpp:
#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;//向右移动
m_row = 0;//初始化蛇头的位置
m_col = 0;
}
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;
}
enum RESOLUTION{
NET_SIZE = 32,NET_WIDTH = 320
};
void SnakeNode::setPositionRC(int row,int col)//设置节点的坐标
{
this->m_row = row;
this->m_col = col;
setPosition(Point(col * NET_SIZE,row * NET_SIZE));
}
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,NET_SIZE * i),Point(NET_WIDTH,1,Color4F(1,1));
draw->drawSegment(Point(NET_SIZE * i,0),Point(NET_SIZE * i,NET_WIDTH),1));
}
//添加蛇头
spHead = SnakeNode::create(1);
this->addChild(spHead);
//添加身体
//添加食物
spFood = SnakeNode::create(3);
//float i = CCRANDOM_0_1()*(end - start + 1) + start;
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::createWithSystemFont("分数: 0","宋体",25);
//auto labelscore = Label::createWithSystemFont("score: 0","AdobeHeitiStd-Regular",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.5f);
//加入用户触摸事件侦听
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [&](Touch * t,Event * e){
//改变贪食蛇移动的方向
int col = t->getLocation().x / NET_SIZE;
int row = t->getLocation().y / NET_SIZE;
int spHeadCol = spHead->getPositionX() / NET_SIZE;
int spHeadRow = spHead->getPositionY() / NET_SIZE;
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.3f,Point(NET_SIZE,0)));
spHead->m_col++;
break;
case ENUM_DIR::DIR_LEFT:
spHead->runAction(MoveBy::create(0.3f,Point(-NET_SIZE,0)));
spHead->m_col--;
break;
case ENUM_DIR::DIR_DOWN:
spHead->runAction(MoveBy::create(0.3f,Point(0,-NET_SIZE)));
spHead->m_row--;
break;
case ENUM_DIR::DIR_UP:
spHead->runAction(MoveBy::create(0.3f,NET_SIZE)));
spHead->m_row++;
break;
default:
break;
}
//add TODO
if (spHead->m_row < 0 || spHead->m_col < 0 ||
spHead->m_row > 9 || spHead->m_col > 9)
{
auto scene = MainMenu::createScene();
Director::getInstance()->replaceScene(scene);
}
//碰撞检测
if (spHead->m_row == spFood->m_row&&
spHead->m_col == spFood->m_col)
{ //音效的播放
SimpleAudioEngine::getInstance()->playEffect("eat.wav");
//分数增加
this->m_score += 100;
auto label = (Label *)this->getChildByTag(110);
char strscore[20];
sprintf(strscore,"分数: %d",m_score);
label->setString(strscore);
//食物产生新的位置
int row = rand() % 10;//0-9
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.3f,0)));
bodynode->m_col++;
break;
case ENUM_DIR::DIR_LEFT:
bodynode->runAction(MoveBy::create(0.3f,0)));
bodynode->m_col--;
break;
case ENUM_DIR::DIR_DOWN:
bodynode->runAction(MoveBy::create(0.3f,-NET_SIZE)));
bodynode->m_row--;
break;
case ENUM_DIR::DIR_UP:
bodynode->runAction(MoveBy::create(0.3f,NET_SIZE)));
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;
}
源码和资源下载地址:
@L_403_0@