学习游戏编程是一件非常有趣的事情,在cocos2dx官网找了几个简单的游戏试试手,感觉也不是那么难,首先来看看2048这款游戏吧,很火的原因之一是因为它简单而易操作。网上这位Legendof1991大神很早就写过了,我大部分代码都是根据他的文章来的,但是也有些细节的地方自己修改了,下面就正是进入游戏吧。

先书写一下整个游戏的流程图:

图1  2048简单流程图

一、主场景的创建

首先还是新建一个工程,名字随便你怎么取,然后按照老规矩该添加图层就添加图层。先来看下它的头文件:

class HelloWorld : public cocos2d::Layer
{
public: // there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); // a selector callback
void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually
CREATE_FUNC(HelloWorld); virtual bool onTouchBegan(Touch *touch, Event *unused_event);
virtual void onTouchEnded(Touch *touch, Event *unused_event); bool doUp();
bool doDown();
bool doLeft();
bool doRight(); //创建卡片函数
void createCard(Size size);
void autoCreateCardNumber();
//判断游戏是否能够继续
void doCheckGameOver();
private:
int firstX,firstY,endX,endY;
CardSprite* cardArray[][];
//游戏得分
int score;
CCLabelTTF *labelTTFScoreName;
CCLabelTTF* labelTTFScoreNumber; }; #endif // __HELLOWORLD_SCENE_H__

其中这两个函数virtual bool onTouchBegan(Touch *touch, Event *unused_event);virtual void onTouchEnded(Touch *touch, Event *unused_event);主要是用来判断触屏滑动的方向。

void HelloWorld::onTouchEnded(Touch *touch, Event *unused_event)
{
Point touchPoint=touch->getLocation();
//touch->getLocationInView();
endX=firstX-touchPoint.x;
endY=firstY-touchPoint.y;
if (abs(endX)>abs(endY))
{
if(endX+>)
{
//向左
doLeft();
}
else
{
//向右
doRight();
}
}
else
{
if(endY+>)
{
//向下
doDown();
}
else
{
//向上
doUp();
}
}
}

这段代码通过世界坐标和窗口坐标之间的差值来判断的,经过测试可行。具体的原理他也没有说明。

二、卡片的创建

卡片我们需要新建一个卡片类来实现,类中我们需要设置一些初始化动作,我把他放在下面这个函数中。

CardSprite* CardSprite::createCardSprite(int numbers,int width,int height,float CardSpriteX,float CardSpriteY)
{
//CardSprite *enemy=new CardSprite();
CardSprite* enemy=CardSprite::create();
//CardSprite* enemy=new CardSprite(); if (enemy&&enemy->init())
{
//enemy->autorelease(); //自动释放,这种写法比较好,如果没有初始化好的话也可以安全删除
enemy->enemyInit(numbers,width,height,CardSpriteX,CardSpriteY);
enemy->retain(); //记得release
return enemy;
}
CC_SAFE_DELETE(enemy); //安全释放
return NULL;
}

其中我们需要注意的地方是如果你用create函数之后,需要retain一次,不需要用了则要release,原文博客中用的是这两句:CardSprite *enemy=new CardSprite();enemy->autorelease();他这样处理的好处就是内存由内存池自动管理了。

三、算法分析

每个游戏核心都是算法处理。2048也不例外,它的核心思想是每行每列遇到相同的数字则一个乘以2,另一个卡片变成0,例如我们向左滑动的时候代码可以这样写,时间复杂度o(N3),其它三个方向的算法思路也是一样的。

bool HelloWorld::doLeft()
{
bool isdo = false;
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{ for (int x1 = x + ; x1 < ; x1++)
{
if (cardArray[x1][y]->getNumbers() > )
{
if (cardArray[x][y]->getNumbers() <= )
{
cardArray[x][y]->setNumbers(cardArray[x1][y]->getNumbers());
cardArray[x1][y]->setNumbers(); x--; //这里不会发生溢出,原来已经x1++了。
isdo = true;
}else if(cardArray[x][y]->getNumbers() == cardArray[x1][y]->getNumbers())
{
cardArray[x][y]->setNumbers(cardArray[x][y]->getNumbers()*);
cardArray[x1][y]->setNumbers();
score+=cardArray[x][y]->getNumbers();
labelTTFScoreNumber->setString(String::createWithFormat("%i",score)->getCString());
isdo = true;
}
break;
}
}
}
}
return isdo;
}

至于当你的卡片消除之后,主层中多于两个卡片空位时,你需要添加两张卡片填充空位,至于位置也是随机分布的,它采用递归的方式寻找没有数字的卡片。来看段代码:

void HelloWorld::autoCreateCardNumber()
{
int i=CCRANDOM_0_1()*; //随机生成数字0-4
int j=CCRANDOM_0_1()*; //随机生成数字
if (cardArray[i][j]->getNumbers()>)
{ //有数字则递归调用直到有空白的地方为止
autoCreateCardNumber();
}
else
{
cardArray[i][j]->setNumbers(CCRANDOM_0_1()*<?:); //乘以10之后看是否小于1,出现2或者4,这里就是卡片出现的概率问题了
} }
四、总结

整个游戏的难点大概就是这些吧,至于其他一些细节的地方大家可以看他的原文,这个游戏主要涉及到的难点就是卡片的消除及消除之后如何再把数字随机的添加到卡片上。下期任务是写一个简单版的打飞机游戏。望诸君共勉!

作者:曹麒文

出处:http://www.cnblogs.com/master-image/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

cocos2d-x游戏之2048的更多相关文章

  1. [LeetCode] Flip Game 翻转游戏之二

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  2. [LeetCode] Jump Game II 跳跃游戏之二

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  3. 猜字符游戏之java

    package days06; //需求......,问题,为什么要用do{}while???import java.util.Scanner;public class RepeatOfGussing ...

  4. 从腾讯QQ升级游戏之“快速加入游戏”功能的实现缺陷看C/S之间如何正确分配相关协作

    转载:http://space.itpub.net/17007506/viewspace-615570 笔者在闲暇时,偶尔会登录腾讯QQGame玩玩升级游戏.这确实是一款非常优秀的软件作品,腾讯的开发 ...

  5. 键盘游戏之canvas--用OO方式写

    虽然写的不是很好,但 解释权以及版权仍然归13东倍所有!  <!DOCTYPE HTML> <html> <head> <title>canvas-00 ...

  6. [Swift]LeetCode294. 翻转游戏之 II $ Flip Game II

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  7. [LeetCode] Flip Game II 翻转游戏之二

    You are playing the following Flip Game with your friend: Given a string that contains only these tw ...

  8. html5游戏之Box2d物理引擎集成

    前面两章我们已经研究了如何使用Box2d来模拟游戏世界,这一章就把所有的东西拼凑在一起,最终完成我们的游戏. 一.定义物体 典型的物体: {type:'ground',name:'dirt',x:50 ...

  9. Unity2D 小游戏之 RocketMouse

    这个小游戏源自这里.这几天闲时捡了点 Unity(很久没有摸它了),顺手将这个小游戏移植到了 Unity5.5.0,除了 Parallax Scrolling 还有点小问题外,其它功能全部完整.部分代 ...

随机推荐

  1. [PowerShell]get data from Ini File

    $filedata = @' app.name=Test App app.version=1.2 '@ $filedata | set-content appdata.txt $AppProps = ...

  2. Linux中***配置

    Ubuntu系统下: 1.执行如下命令 sudo apt install shadowsocks polipo 2.创建 shadowsocks.json 配置文件,放在你想放的位置 { " ...

  3. P1111 修复公路(并查集)

    题目背景 AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数NN,和公路数MM,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你 ...

  4. input只能输入非负数

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. dedecms模板目录

    根目录 /dede 管理后台目录 /freelist 自由文档列表生成目录 /html 默认文章生成目录 /include 程序核心文件目录 /member 会员管理目录 /plus 插件及辅助功能目 ...

  6. Ubuntu 14.04下MySQL服务器和客户端的安装

    下面进行简单的配置 安装完成后通过修改/etc/mysql/my.cnf(此文件为mysql的配置文件).将文件中的binding-address=127.0.0.1注释掉.其它配置根据需要更改. H ...

  7. java 数据库连接

    一.JDBC(Java Database Connectivity) JDBC是Java语言中访问数据库的应用程序接口,可以为多种关系数据库提供统一访问. jdbc.properties jdbc.d ...

  8. 10.Web组件复用

    1.静态包含(一个指令) 在软件工程中构建可复用组件可极大的提高软件生产效率.增强系统的可维护性HTML标记对于一个web应用系统中的页面都是通用的,比如公司标志.版权声明.导航菜单JSP中引用的we ...

  9. my11_mysql事务隔离

    概述 ************************************************ Mysql有四个事务隔离级别,默认隔离级别为RR,开启一个事务可以使用 START TRANSA ...

  10. Microsoft使用技巧

    1.拍摄屏幕内容的截图 按 Win + Shift + S 以打开截图栏,然后将光标拖动到要捕获的区域. 截图区域将保存到剪贴板. 2.使用键盘添加表情符号 随心随处表达自我. 按 Ctrl + Sh ...