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

cocos2d-x-3.0从零到2048游戏开发

2016-06-14 16:23 375 查看
为了做C++的课程设计,对自己学的C++语言进行应用,4月底开始,从零开始学了Cocos2d-x游戏开发,今天课设作业检查成绩不错,趁热做一下总结。

本博客为上篇,记录关于下载相应软件和环境的配置以及新建项目的步骤。

环境:windows10

下载:VS2013,python2.7.8,cocos2d-x.3.0


游戏开发前准备

1、下载VS2013

官网下载Visual Studio,我的版本为VS2013

https://www.visualstudio.com/zh-cn/downloads/download-visual-studio-vs.aspx


VS下载时间较长,需耐心等待

2、python2.7.8环境

装python,因为cocos2d-x 是基于python的游戏开发工具,需配置好python环境。一定要记得自己的安装路径,我的路径为E:\ProgramFiles(x86)\python-2.7.8.amd64\Python27。建议安装在根目录如D:\Python , 路径名不要有空格,打开我的电脑,点击右键属性-高级系统设置-环境变量,在系统变量中有一个Path的变量,将自己的python的安装路径粘贴到上面,与以前的path中内容之间记得写英文分号“;”。

检查是否安装好python。

打开运行菜单,输入cmd确定,再输入python,如果在页面中显示出“python”不是内部或外部命令,说明环境没有配置好,如果在菜单中显示python的版本号,说明已经安装并配置完成

3、cocos2d-x.3.0

官网下载,较简单。我的路径E:\ProgramFiles(x86)\cocos2d-x-3.0\cocos2d-x-3.0,建议路径中不要有括号。

http://www.cocos2d-x.org/products

4、初次运行

打开解压好的cocos2d-x,最下面有一个setup.py文件。打开运行菜单输入cmd确定,将setup.py拖入,回车。



因为我的路径在e盘,而默认在c盘,需先进入e盘:输入“e:”后回车,我的路径中有括号,只能先进入路径后再把setup.py拖入。

打开cocos2d-x中的build的文件夹,在build文件夹中有一个cocos2d-win32.vc2012.sln的可运行文件,双击打开,右键单击图片中所指出的项目,设置为启动项 然后点击调试器运行,由于第一次运行,时间可能会长一点点。





运行后界面



5、新建自己的项目,以2048游戏项目为例

在控制台中输入e:回车,cd 进入自己的路径()E:\ProgramFiles(x86)\cocos2d-x-3.0\cocos2d-x-3.0\tools\cocos2d-console\bin 点击回车

最后创建一个新的Demo: cocos new 2048(文件的名称) –l(语言language) cpp (C++)–d D:\C++\Cocos2d-x(建在D:\C++\Cocos2d-x目录下,若不写默认bin目录)

打开 2048 - proj.win32 - 2048.sln 打开后,运行自己的新建的项目,运行效果



6、代码解析

自己起初什么都不懂时看的学长给的代码解析,对自己的cocos入门有较大帮助,这里复制过来分享。

AppDelegate.cpp解析





HelloWorld.cpp代码解析







7、软件下载阶段总结

万事开头难,下载软件都不是一次完成的,为了下载vs甚至重装了系统(虽然浪费了好多时间,但是电脑变得干净有条理了,开机也快了,也是一件大好事),找一本好资料也不容易,也去图书馆借了好多书,但只要多学多问,突破了就好了。

2048游戏开发阶段

参考极客学院Mac系统下2048游戏,并参考博文:http://blog.csdn.net/wwj_748/article/details/38168649,动手编写了windows系统下基于cocos2d-x-3.0版本的2048PC端游戏。

难点:游戏逻辑,上下手势的识别

过程:

1、游戏实现效果

2、Cocos2d-x中上下左右手势的识别

3、游戏中卡片类的创建

4、添加卡片到游戏中

5、游戏中的逻辑实现

6、游戏中随机卡片的生成

7、游戏结束判断

8、游戏分数的添加

9、游戏美化

1、游戏实现效果



根据鼠标左右拖动,实现方块的左右移动,每拖动一次,所有的数字方块都会往滑动的方向靠拢外,同时在空白的地方出现一个数字方块(2或4),相同数字的两个方块在相撞时会相加成一个新方块。

2、Cocos2d-x中上下左右手势的识别

在HelloWorldScene.h中声明两个需要实现的监听事件,并在HelloWorldScene.cpp中具体实现

声明鼠标点击的两个方法

//手势事件
virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);


鼠标上下左右的方法

//上下左右参数
bool doLeft();
bool doRight();
bool doUp();
bool doDown();


private:
//点击的元素d位置
int firstX, firstY, endX, endY;


HelloWorldScene.cpp中实现

bool HelloWorld::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event) {
Point touchPO = touch->getLocation();
firstX = touchPO.x;
firstY = touchPO.y;
return true;
}
void HelloWorld::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event) {
//得到xy 的移动范围
Point touchPO = touch->getLocation();

endX = firstX-touchPO.x;
endY = firstY-touchPO.y;

//判断x y轴移动距离,如果x>y左右,否则上下
if (abs(endX) > abs(endY)) {
//左右
if (endX + 5 > 0) {
if (doLeft()){
autoCreateCardNumber();
doCheckGameOver();
}
}
else {
if (doRight()){
autoCreateCardNumber();
doCheckGameOver();
}

}
}else {
//上下
if (endY + 5 > 0) {
if (doDown()){
autoCreateCardNumber();
doCheckGameOver();
}
}
else{
if (doUp()){
autoCreateCardNumber();
doCheckGameOver();
}
}
}
}

在HelloWorld的init方法中设置鼠标点击的监听的方法

<p><span style="font-family: KaiTi_GB2312;"><span style="font-size:12px;">//加入监听事件</span></span></p><span style="font-size:14px;">	auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(touchListener,</span>


3、游戏中卡片类的创建
新建卡片类,注意更改路径为Classes路径下,卡片类是一个精灵类,继承sprite

class CardSprite:public cocos2d::Sprite {

public:
//初始化游戏卡片
static CardSprite *createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
virtual bool init();
CREATE_FUNC(CardSprite);

//得到和改变数字
void setNumber(int num);
int getNumber();

private:
int number;
//初始化数字方法
void enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
//定义显示数字的控件
cocos2d::LabelTTF *labelTTFCardNumber;
cocos2d::LayerColor *layercolorBG;

};

具体实现

#include "CardSprite.h"
USING_NS_CC;
CardSprite* CardSprite::createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {

CardSprite *enemy = new CardSprite();
if (enemy &&enemy->init()) {
enemy->autorelease();
enemy->enemyInit(numbers, width, height, CardSpriteX, CardSpriteY);
return enemy;
}
CC_SAFE_DELETE(enemy);
return NULL;
}
void CardSprite::enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {
//初始化
number = numbers;
//加入游戏卡片的颜色,宽度高度减10是为了给每一个方块留一个白边
layercolorBG = cocos2d::LayerColor::create(cocos2d::Color4B(255, 255, 240, 155), width - 10, height - 10);
layercolorBG->setPosition(cocos2d::Point(CardSpriteX, CardSpriteY));

//判断如果不等于0就显示
if (number > 0) {
labelTTFCardNumber = cocos2d::LabelTTF::create(__String::createWithFormat("%i", number)->getCString(), "HirakakuProN-W6", 80);
labelTTFCardNumber->setPosition(cocos2d::Point(layercolorBG->getContentSize().width / 2, layercolorBG->getContentSize().height / 2));
layercolorBG->addChild(labelTTFCardNumber);
}
else{
labelTTFCardNumber = cocos2d::LabelTTF::create("", "HirakakuProN-W6", 80);
labelTTFCardNumber->setPosition(cocos2d::Point(layercolorBG->getContentSize().width / 2, layercolorBG->getContentSize().height / 2));
layercolorBG->addChild(labelTTFCardNumber);
}
this->addChild(layercolorBG);
}

bool CardSprite::init() {
if (!Sprite::init()) {
return false;
}
return true;
}

int CardSprite::getNumber() {
return number;
}

void CardSprite::setNumber(int num) {
number = num;

//更新显示的数值
if (number > 0) {
labelTTFCardNumber->setString(__String::createWithFormat("%i",number)->getCString());
}
else {
labelTTFCardNumber->setString("");
}

}


4、添加卡片到游戏中

卡片放置在4*4方框中的不同位置,首先我们需要计算出每张卡片的宽高,然后计算每张卡片所在的位置,最后进行显示。

先在HelloWorld的init()方法中获得屏幕大小

Size winSize = Director::getInstance()->getWinSize();


在HelloWorldScene.h头文件中声明创建卡片的方法,在.cpp的init()中调用。方法具体实现:

<span style="font-size:14px;">//传进屏幕的大小
void HelloWorld::createCardSprite(cocos2d::Size size) {
//求出单元格的宽度和高度
int d = (size.height - 200) / 4;
//创建4*4单元格
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//创建0卡片,宽高均为d,位置为</span><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;">d*i + size.width/4,size.width/4是最左边卡片开始的水平位置,每一个右移一个d,高度同理。</span></span><span style="font-size:14px;">

CardSprite *card = CardSprite::createCardSprite(0,d,d,d*i + size.width/4,d*j+20+size.height/12);
addChild(card);

cardArr[i][j] = card;
}

}
}</span>

5、游戏中的逻辑实现

<span style="font-size:12px;">//上下左右参数
bool HelloWorld::doLeft() {
bool isdo = false;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
for (int x1 = x + 1; x1 < 4; x1++) {
if (cardArr[x1][y]->getNumber()>0) {//右边有卡片,如果自己为空,则等于右边卡片数,右边卡片设为0
if (cardArr[x][y]->getNumber() <= 0){
cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
cardArr[x1][y]->setNumber(0);
x--;
isdo = true;
}//如果右边卡片等于自己,则自己乘2,右边设为0
else if (cardArr[x1][y]->getNumber() == cardArr[x][y]->getNumber()){
cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
cardArr[x1][y]->setNumber(0);
score += cardArr[x][y]->getNumber();
labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
isdo = true;
}
break;
}
}
}
}
return isdo;
}
bool HelloWorld::doRight() {
bool isdo = false;
for (int y = 0; y < 4; y++) {
for (int x = 3; x >= 0; x--) {
for (int x1 = x - 1; x1 >= 0; x1--) {
if (cardArr[x1][y]->getNumber()>0) {
if (cardArr[x][y]->getNumber() <= 0){
cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
cardArr[x1][y]->setNumber(0);
x++;
isdo = true;
}
else if (cardArr[x1][y]->getNumber() == cardArr[x][y]->getNumber()){
cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
cardArr[x1][y]->setNumber(0);

score += cardArr[x][y]->getNumber();
labelTTFCardNumber->setString(__String::createWithFormat("%i",score)->getCString());
isdo = true;

}
break;
}
}
}
}
return isdo;
}
bool HelloWorld::doUp() {
bool isdo = false;
for (int x = 0; x < 4; x++) {
for (int y = 3; y >= 0; y--) {
for (int y1 = y - 1; y1 >= 0; y1--) {
if (cardArr[x][y1]->getNumber()>0) {
if (cardArr[x][y]->getNumber() <= 0){
cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
cardArr[x][y1]->setNumber(0);
y++;
isdo = true;
}
else if (cardArr[x][y1]->getNumber() == cardArr[x][y]->getNumber()){
cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
cardArr[x][y1]->setNumber(0);
score += cardArr[x][y]->getNumber();
labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
isdo = true;
}
break;
}
}
}
}
return isdo;
}
bool HelloWorld::doDown() {
bool isdo = false;
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
for (int y1 = y + 1; y1 <4; y1++) {
if (cardArr[x][y1]->getNumber()>0) {
if (cardArr[x][y]->getNumber() <= 0){
cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
cardArr[x][y1]->setNumber(0);
y--;
isdo = true;
}
else if (cardArr[x][y1]->getNumber() == cardArr[x][y]->getNumber()){
cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
cardArr[x][y1]->setNumber(0);
score += cardArr[x][y]->getNumber();
labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
isdo = true;
}
break;
}
}
}
}
return isdo;
}</span>


6、游戏中随机卡片的生成

在HelloWorldScene.h头文件中声明随机生成,在HelloWorldScene.cpp实现该方法。先随机找到一个位置,若此位置卡片数字大于0,生成卡片数字.且数字为2或4

void HelloWorld::autoCreateCardNumber(){
//生成卡片的位置的xy
int i = CCRANDOM_0_1() * 4;
int j = CCRANDOM_0_1() * 4;
//判断是否已经存在的位置
if (cardArr[i][j]->getNumber() > 0) {
autoCreateCardNumber();
}
else{
cardArr[i][j]->setNumber(CCRANDOM_0_1() *10<1?4:2);
}

}


7、游戏结束判断

在HelloWorldScene.h头文件中声明,在HelloWorldScene.cpp实现该方法。

// 判断游戏是否还能继续运行下去
void HelloWorld::doCheckGameOver(){
//左右都没有相同的,则运行不下去
bool isGameOver = true;

for (int y = 0; y < 4;y++) {
for (int x = 0; x < 4;x++){
if (cardArr[x][y]->getNumber() == 0
|| (x>0 && (cardArr[x][y]->getNumber() == cardArr[x - 1][y]->getNumber()))
|| (x < 3 && (cardArr[x][y]->getNumber() == cardArr[x + 1][y]->getNumber()))
|| (y < 0 && (cardArr[x][y]->getNumber() == cardArr[x][y - 1]->getNumber()))
|| (y < 3 && (cardArr[x][y]->getNumber() == cardArr[x][y + 1]->getNumber()))) {
isGameOver = false;
}
}
}
if (isGameOver) {
// 结束游戏
Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
}

}


8、游戏分数的添加

在HelloWolrdScene.h文件中声明分数和显示分数的控件,在.cpp中的init()方法中实现,并将分数初始化为0,这里的控件用的是label。

//在上方加入游戏的分数
auto label1 = Label::createWithSystemFont("GRADE","HirakakuProN-W6",50);
label1->setPosition(Point(winSize.width/3,winSize.height*7/8));
addChild(label1);

auto label2 = Label::createWithSystemFont(":", "HirakakuProN-W6", 50);
label2->setPosition(Point(winSize.width / 2, winSize.height * 7/8));
addChild(label2);

labelTTFCardNumber = LabelTTF::create("0", "HirakakuProN-W6", 50);
labelTTFCardNumber->setPosition(Point(winSize.width * 3 / 5, winSize.height * 7 / 8));
addChild(labelTTFCardNumber);


9、游戏美化

我把游戏设置成了绿色的感觉,这样比较舒服,是在ps里面选择的颜色然后用它的RGB数值。

在HelloWorldScene.cpp的init()方法中设置背景颜色。

//加入游戏的背景
auto layercolorBG = cocos2d::LayerColor::create(cocos2d::Color4B(200, 220, 180, 255));
this->addChild(layercolorBG);


在CardSprite的setNumber方法中设置卡片颜色,卡片大小(不同的数字的颜色不同,显示的字体大小不同)。

void CardSprite::setNumber(int num) {
number = num;

//根据大小调整字体
if (number >= 0) {
labelTTFCardNumber->setFontSize(80);
}
if (number >= 16) {
labelTTFCardNumber->setFontSize(70);
}
if (number >= 128) {
labelTTFCardNumber->setFontSize(60);
}
if (number >= 1024) {
labelTTFCardNumber->setFontSize(50);
}

switch (number) {
case 0:
layercolorBG->setColor(cocos2d::Color3B(255, 255, 240));
break;
case 2:
layercolorBG->setColor(cocos2d::Color3B(230, 255, 190));
break;
case 4:
layercolorBG->setColor(cocos2d::Color3B(190, 255, 180));
break;
case 8:
layercolorBG->setColor(cocos2d::Color3B(160, 255, 100));
break;
case 16:
layercolorBG->setColor(cocos2d::Color3B(130, 255, 80));
break;
case 32:
layercolorBG->setColor(cocos2d::Color3B(95, 177, 62));
break;
case 64:
layercolorBG->setColor(cocos2d::Color3B(156, 190, 90));
break;
case 128:
layercolorBG->setColor(cocos2d::Color3B(237, 229, 140));
break;
case 256:
layercolorBG->setColor(cocos2d::Color3B(200, 190, 180));
break;
case 512:
layercolorBG->setColor(cocos2d::Color3B(247, 250, 166));
break;
case 1024:
layercolorBG->setColor(cocos2d::Color3B(255, 255, 0));
break;
case 2048:
layercolorBG->setColor(cocos2d::Color3B(200, 130, 40));
break;
case 4296:
layercolorBG->setColor(cocos2d::Color3B(200, 40, 40));
break;
case 8592:
layercolorBG->setColor(cocos2d::Color3B(137, 52, 74));
break;
case 17184:
layercolorBG->setColor(cocos2d::Color3B(0, 0, 0));
break;

}

//更新显示的数值
if (number > 0) {
labelTTFCardNumber->setString(__String::createWithFormat("%i",number)->getCString());
}
else {
labelTTFCardNumber->setString("");
}

}


源码在我参考的那篇博文里有,我的稍微有不同,但是具体实现都是一样的,建议根据极客学院一步一步来

昨天让老师检查课设作业,也发现好多大神,自己还得努力,将来自己能从设计到实现做一个完整的项目。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: