Cocos2d-x开发wp8版贪吃蛇全程纪实

:891: 本人从Android出入cocos2dx大门。。。途中是各种坎坷。。
按照http://www.cocoachina.com/bbs/read.php?tid=197370&page=1 该章节的内容copy 一下,小写了个贪吃蛇。大概算是一只脚踏入了大家庭的门。本来想把游戏界面的画面改得更美观些。无奈学习的东西还不够多。draw这方面的东西实在欠缺。忘大家见谅,下面开始介绍:
一:使用环境:win8.1+vs2013+cocos2dx3.0rc2;
二:环境搭建步骤:
准备事项:需要下载以下几个东西:
1:微软VS2012以上版本。下载地址:
VS2012:http://www.microsoft.com/zh-cn/download/details.aspx?id=30678http://www.microsoft.com/zh-cn/download/details.aspx?id=30678
VS2013:http://www.microsoft.com/zh-cn/download/details.aspx?id=42307http://www.microsoft.com/zh-cn/download/details.aspx?id=42307
WP8.0SDK:http://www.microsoft.com/zh-cn/download/details.aspx?id=35471http://www.microsoft.com/zh-cn/download/details.aspx?id=35471
2:python:我们使用2.7版本。3.0版本在使用时会有问题,因此建议使用2.7.如果用3.0有解决方法的也可以回帖告知下;
下载地址:https://www.python.org/downloads/https://www.python.org/downloads/
3:cocos2d-x-3.0rc2:
下载地址:http://www.cocos2d-x.org/downloadhttp://www.cocos2d-x.org/download
弄wp8环境可谓是九九八十一难啊。。。。各种纠结的问题。注意事项,记得各位基友看看自己的电脑必须是win8 pro以上系统,配置的话需要cpu支持硬件虚拟化才能运行虚拟机啊亲。微软这是要被大家扔砖的节奏啊。
(1)我们需要在win8或者win8.1上安装vs2013,如果已经安装了2012可以选择增加一个wp8.0sdk。。。不大。“也就”1G多。。。准备好腾出C盘宝贵的空间,让你们的仓老湿,波老湿们先挪个作品到垃圾箱去吧。微软的产品安装步骤基本就是下一步下一步。如果是vs2013记得勾选wp环境选项
(2)安装完VS,安装python,也是各种下一步。完毕之后,在系统环境中配置添加安装路径。
(3)下载cocos2d-x-3.0rc2.解压。打开命令行,把setup.py拉进去。因为本身有Android环境,就把提示的sdk,ndk,ant路径都配置了。系统环境自动生成了一些cocos的变量。

三:创建项目
打开命令行,输入创建命令:cocos new mygame -l cpp-d E:\cocos\mygame
注意:这里设置的路径是cocos安装路径底下再建一个文件。可能是rc2对wp8的支持还不是很完善,如果建在其他目录就很容易出现引用项目无法找到的蛋碎情形,因此我都建在了cocos安装目录底下再加一层目录。这样基本上项目就不会再出错;

四:开始开发
1:了解项目结构:
WP8的这个C#项目直接无视,貌似如果要修改启动名称跟图标要从这里改,cocos是夸平台,直接修改引用的C++代码就OK真心给力。因此我们只需要修改HelloCppComponent中Classes文件夹下的C++代码;
Classes下代码有四个:
AppDelegate.cpp
AppDelegate.h
HelloWorldScene.cpp
HelloWorldScene.h

AppDelegate的两个文件应该是入口文件。就不做任何修改。
HelloWorldScene的就是默认页的相关代码了。
我的理解就是.h文件声明类以及相关接口,.cpp实现具体功能。只是个人观点。不会C++请谅解;
恶补了一下,cocos的导演,场景等等基础知识后,了解了HelloWorld所做的一些事情.具体都在代码中注释鸟。不一一解释。
2:流程
主菜单->帮助页->游戏页面。
3:开始开发:
首先,我们设计一个主菜单:含几个菜单选项:开始游戏,游戏帮助,退出游戏
.h文件中代码

 

//游戏主菜单画面 
class HelloWorld : public cocos2d::Layer 
{ 
public: 
static cocos2d::Scene* createScene();//创建主菜单画面的场景 
virtual bool init(); //初始化操作 
//菜单项点击事件 
void menuCloseCallback(Ref* pSender); 
void menuStartCallback(Ref* pSender); 
void menuHelpCallback(Ref* pSender); 

CREATE_FUNC(HelloWorld); 
}; 


```
 
.cpp代码: 

 

Scene* HelloWorld::createScene() 
{ 
auto scene = Scene::create(); 
auto layer = HelloWorld::create(); 
scene->addChild(layer); 

return scene; 
} 

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

Size visibleSize = Director::getInstance()->getVisibleSize(); 
Point origin = Director::getInstance()->getVisibleOrigin(); 

//在界面上添加菜单内容 

//添加关闭程序按钮 
auto closeItem = MenuItemImage::create( 
"CloseNormal.png",//默认显示图片 
"CloseSelected.png",//点击按下显示图片 
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));//绑定点击事件 

closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width / 2, 
origin.y + closeItem->getContentSize().height / 2));//设定显示位置为屏幕宽度-控件自身宽高一半。也就是显示在右下角 


//添加开始按钮 
auto startMenu = MenuItemImage::create( 
"btn_start.png", 
"btn_start.png", 
CC_CALLBACK_1(HelloWorld::menuStartCallback, this)); 

startMenu->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y + 50)); 

//添加帮助按钮 
auto helpMenu = MenuItemImage::create( 
"btn_help.png", 
"btn_help.png", 
CC_CALLBACK_1(HelloWorld::menuHelpCallback, this)); 

helpMenu->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); 
//添加退出按钮 
auto exitMenu = MenuItemImage::create( 
"btn_exit.png", 
"btn_exit.png", 
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 

exitMenu->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y - 50)); 


//创建菜单载体,将上面的菜单内容都添加到载体中 
auto pMenu = Menu::create(startMenu, helpMenu, exitMenu, closeItem, NULL);//添加制定的菜单项 
pMenu->setPosition(Point::ZERO);//设置显示位置 
this->addChild(pMenu, 1);//添加到场景中 


//制定游戏背景 
auto sprite = Sprite::create("HelloWorld.png"); 
sprite->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); 
this->addChild(sprite, 0); 

//------------------------ 

return true; 
} 


//退出按钮事件 
void HelloWorld::menuCloseCallback(Ref* pSender) 
{ 
//Director::getInstance()->replaceScene(GameHelp::createScene()); 
Director::getInstance()->end(); 
} 
//开始游戏按钮事件 
void HelloWorld::menuStartCallback(Ref* pSender) 
{ 
Director::getInstance()->replaceScene(GameLayer::createScene()); 
//Director::getInstance()->end(); 
} 
//帮助按钮事件 
void HelloWorld::menuHelpCallback(Ref* pSender) 
{ 
Director::getInstance()->replaceScene(GameHelp::createScene()); 
//Director::getInstance()->end(); 
} 


```
 

再菜单中监听相关按钮实现场景切换。 
接下来,设计一个帮助页,事件关系只写了菜单及调整: 
.h代码: 

 

//游戏帮助画面 
class GameHelp :public cocos2d::Layer 
{ 
public : 
virtual bool init();//初始化 
//按钮事件监听 
void menuGoGameCallback(Ref* pSender); 
void menuGoMainCallback(Ref* pSender); 
static cocos2d::Scene * createScene();//创建帮助画面 
CREATE_FUNC(GameHelp); 
}; 


```
 
 

bool GameHelp::init() 
{ 
if (!Layer::init()) 
{ 
return false; 
} 
Size visibleSize = Director::getInstance()->getVisibleSize(); 
Point origin = Director::getInstance()->getVisibleOrigin(); 
//添加退出按钮 
auto gotogameMenu = MenuItemImage::create( 
"btn_gotogame.png", 
"btn_gotogame.png", 
CC_CALLBACK_1(GameHelp::menuGoGameCallback, this)); 

gotogameMenu->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); 

auto goMainMenu = MenuItemImage::create( 
"btn_gomain.png", 
"btn_gomain.png", 
CC_CALLBACK_1(GameHelp::menuGoMainCallback, this)); 

goMainMenu->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y - 50)); 

auto pMenu = Menu::create(gotogameMenu, goMainMenu, NULL); 
pMenu->setPosition(Point::ZERO); 
this->addChild(pMenu, 1); 

auto sprite = Sprite::create("HelloWorld.png"); 
sprite->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); 
this->addChild(sprite, 0); 
return true; 
} 
//帮助按钮事件 
void GameHelp::menuGoGameCallback(Ref* pSender) 
{ 
Director::getInstance()->replaceScene(GameLayer::createScene()); 
} 

//帮助按钮事件 
void GameHelp::menuGoMainCallback(Ref* pSender) 
{ 
Director::getInstance()->replaceScene(HelloWorld::createScene()); 
} 



//获取帮助画面 
Scene * GameHelp::createScene() 
{ 
auto scene = Scene::create(); 
auto hl = GameHelp::create(); 
scene->addChild(hl); 
return scene; 
} 


```
 

帮助画面仅提供跳转。 
接下来,设计游戏界面,由于对draw不熟悉,基本都是copy案例中的代码。 
.h代码: 

 
//标识贪食蛇的移动方向 
typedef enum { 
UP=1, 
DOWN, 
LEFT, 
RIGHT 
}DIR_DEF; 

//定义每一节蛇元素的属性,包含了所在行,列,移动方向 
class SnakeNode :public cocos2d::Ref{ 
public: 
int row;//行 
int col;//列 
int dir;//方向 
}; 
//游戏画面 
class GameLayer :public cocos2d::Layer 
{ 
protected: 
SnakeNode *sHead; //创建蛇对象 
SnakeNode *sFood; //食物对象 
cocos2d::Vector allBody;//蛇的身体 
cocos2d::Texture2D * chead; 
public : 
virtual bool init();//初始化 

virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override; 

//监听触摸事件 
bool onTouchBegan(cocos2d::Touch* touch, Event *event); 

void timesthing(float t);//定时事件 
static cocos2d::Scene * createScene();//创建游戏画面 
CREATE_FUNC(GameLayer); 
}; 


```
 

.cpp代码 
 

//初始化游戏层 
bool GameLayer::init() 
{ 
if (!Layer::init()) 
{ 
return false; 
} 
Size visibleSize = Director::getInstance()->getVisibleSize(); 
Point origin = Director::getInstance()->getVisibleOrigin(); 


auto goMainMenu = MenuItemImage::create( 
"btn_gomain.png", 
"btn_gomain.png", 
](Ref* sender){ 
Director::getInstance()->replaceScene(HelloWorld::createScene()); 
}); 

goMainMenu->setPosition(Point(origin.x + visibleSize.width - goMainMenu->getContentSize().width / 2, 
origin.y +visibleSize.height + goMainMenu->getContentSize().height / 2)); 

auto pMenu = Menu::create(goMainMenu, NULL); 
pMenu->setPosition(Point::ZERO); 
this->addChild(pMenu, 1); 


auto labhelp = LabelTTF::create("this is game", "Arial", 15); 
labhelp->setPosition(Point(visibleSize.width + origin.x, visibleSize.height + origin.y)); 
this->addChild(labhelp); 

auto labback = LabelTTF::create("MainMenu", "Arial", 15); 
auto miback = MenuItemLabel::create(labback, ](Ref* sender) 
{ 
Director::getInstance()->replaceScene(HelloWorld::createScene()); 
}); 
miback->setPosition(Point(visibleSize.width + origin.x - miback->getContentSize().width / 2, visibleSize.height + origin.y - miback->getContentSize().height / 2)); 

this->addChild(miback); 



chead = ::CCTextureCache::sharedTextureCache()->addImage("head.png"); 
//监听触摸事件 
auto listener = EventListenerTouchOneByOne::create(); 
listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);//指定触摸的回调函数 
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);//将listener放入事件委托中 

//初始化蛇头坐标和食物的坐标 
sHead = new SnakeNode(); 
sHead->row = rand() % 10; 
sHead->col = rand() % 10; 

//初始化食物的坐标 
sFood = new SnakeNode(); 
sFood->row = rand() % 10; 
sFood->col = rand() % 10; 


//执行定时事件 
this->schedule(schedule_selector(GameLayer::timesthing), 0.5); 
return true; 
} 

//创建游戏场景 
Scene * GameLayer::createScene() 
{ 
auto scene = Scene::create(); 
auto hl = GameLayer::create(); 
scene->addChild(hl); 
return scene; 

} 



void GameLayer::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) 
{ 
Size visibleSize = Director::getInstance()->getVisibleSize(); 
Point origin = Director::getInstance()->getVisibleOrigin(); 

///绘制形状 
::glLineWidth(2);//设定画线的宽度 
for (int i = 0; i < 11; i++) 
{ 
DrawPrimitives::drawLine(Point(0, i * 32), Point(320, i * 32));//绘制条横线 
DrawPrimitives::drawLine(Point(i * 32, 0), Point(i * 32, 320));//绘制条竖线 
} 


//绘制蛇头 
DrawPrimitives::drawSolidRect(Point(sHead->col * 32 + 2, sHead->row * 32 + 2), 
Point(sHead->col * 32 + 32, sHead->row * 32 + 32), 
Color4F(Color3B(255, 0, 0))); 

//绘制食物 
DrawPrimitives::drawSolidRect(Point(sFood->col * 32 + 2, sFood->row * 32 + 2), 
Point(sFood->col * 32 + 32, sFood->row * 32 + 32), 
Color4F(Color3B(0, 0, 255))); 

//绘制身体 
for (int i = 0; i < allBody.size(); i++) 
{ 
SnakeNode * node = (SnakeNode *)allBody.at(i); 
DrawPrimitives::drawSolidRect(Point(node->col * 32 + 2, node->row * 32 + 2), 
Point(node->col * 32 + 32, node->row * 32 + 32), 
Color4F(Color3B(0, 0, 255))); 
} 

} 

bool GameLayer::onTouchBegan(Touch* touch, Event *event) 
{ 
auto p = touch->getLocation(); 

int nowrow; //当前用户触摸的行 
nowrow = ((int)p.y) / 32; 
int nowcol; //当前用户触摸的列 
nowcol = ((int)p.x) / 32; 

if (abs(nowrow - sHead->row) > abs(nowcol - sHead->col)) //上下移动 
{ 
if (nowrow > sHead->row) 
{ 
sHead->dir = DIR_DEF::UP; 
} 
else 
{ 
sHead->dir = DIR_DEF::DOWN; 
} 

} 
else //左右移动 
{ 
if (nowcol > sHead->col) 
{ 
sHead->dir = DIR_DEF::RIGHT; 
} 
else 
{ 
sHead->dir = DIR_DEF::LEFT; 
} 
} 
CCLOG("rand %d", rand()); 
CCLOG("you touchbegan%f,%f", p.x, p.y); 

return true; 
} 



//定时器回调 
void GameLayer::timesthing(float t) 
{ 
//移动蛇的身体 
for (int i = allBody.size() - 1; i >= 0; i--) 
{ 
SnakeNode * sn = (SnakeNode *)allBody.at(i); 

if (i > 0) 
{ 
SnakeNode * snpre = (SnakeNode *)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; 
}; 

//碰撞检测 
if (sHead->row == sFood->row && sHead->col == sFood->col) 
{ 
//食物消失 
sFood->row = rand() % 10; 
sFood->col = rand() % 10; 

//添加身体到集合 
SnakeNode * sn = new SnakeNode(); 
SnakeNode * lastNode = NULL; 
if (allBody.size() > 0) 
lastNode = (SnakeNode *)allBody.back(); 
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; 
} 
this->allBody.pushBack(sn); 
} 


```
 

OK,设计完毕。编译一下骚等片刻,编译完成后,就可以运行查看效果了。如果cpu不支持硬件虚拟化无法创建虚拟机只能链接真机调试。我得电脑支持,因此直接运行,开启虚拟机查看效果: 
主菜单:  帮助页:  游戏页: 
 贪吃蛇_WP8版.rar (2652 KB)

给楼主点赞!给WP8点赞!!

只是楼主说的那几位老湿我都不认识!:14::14::14:

:14:难道版主大大认识的都是欧美的老湿?

您的文章已被推荐到CocoaChina首页热门文章精选,感谢您的分享。

:880:没用过WP8

WP8啊…很高端的样子啊…

整个游戏的唯一需要思考的地方就是用集合来记录保存身体长度,以及各节身体的坐标信息。

恩。因为还没有很深入了解。暂时只能这样做。应该有更好的方法能实现我觉得

呵呵,其实跟开发其他平台一样的。只是发布跟环境不一样

:866:谢谢大神赏脸

:14:必须赞32个

无图无真相啊

介绍wp8移植的东西很少,没太多参考价值

跪求楼主知道怎么加lua代码在wp8里面吗?????

wp8 好奇葩

:2: :2: :2: :2:

没用过wp8,:14:

楼主你好,如果是cocos2dx2.2.6 C++ 和lua开发环境,怎么将游戏移植到wp8呢? 我现在移植 真机测试遇到lua和c++ 调用的地方崩溃,不知道这方面是否可以提供点参考