cocos2d-x游戏之2048
学习游戏编程是一件非常有趣的事情,在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的更多相关文章
- [LeetCode] Flip Game 翻转游戏之二
You are playing the following Flip Game with your friend: Given a string that contains only these tw ...
- [LeetCode] Jump Game II 跳跃游戏之二
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- 猜字符游戏之java
package days06; //需求......,问题,为什么要用do{}while???import java.util.Scanner;public class RepeatOfGussing ...
- 从腾讯QQ升级游戏之“快速加入游戏”功能的实现缺陷看C/S之间如何正确分配相关协作
转载:http://space.itpub.net/17007506/viewspace-615570 笔者在闲暇时,偶尔会登录腾讯QQGame玩玩升级游戏.这确实是一款非常优秀的软件作品,腾讯的开发 ...
- 键盘游戏之canvas--用OO方式写
虽然写的不是很好,但 解释权以及版权仍然归13东倍所有! <!DOCTYPE HTML> <html> <head> <title>canvas-00 ...
- [Swift]LeetCode294. 翻转游戏之 II $ Flip Game II
You are playing the following Flip Game with your friend: Given a string that contains only these tw ...
- [LeetCode] Flip Game II 翻转游戏之二
You are playing the following Flip Game with your friend: Given a string that contains only these tw ...
- html5游戏之Box2d物理引擎集成
前面两章我们已经研究了如何使用Box2d来模拟游戏世界,这一章就把所有的东西拼凑在一起,最终完成我们的游戏. 一.定义物体 典型的物体: {type:'ground',name:'dirt',x:50 ...
- Unity2D 小游戏之 RocketMouse
这个小游戏源自这里.这几天闲时捡了点 Unity(很久没有摸它了),顺手将这个小游戏移植到了 Unity5.5.0,除了 Parallax Scrolling 还有点小问题外,其它功能全部完整.部分代 ...
随机推荐
- 有趣的数 zoj 月赛
题目描述 让我们来考虑1到N的正整数集合.让我们把集合中的元素按照字典序排列,例如当N=11时,其顺序应该为:1,10,11,2,3,4,5,6,7,8,9. 定义K在N个数中的位置为Q(N,K),例 ...
- CF352A Jeff and Digits
Jeff's got n cards, each card contains either digit 0, or digit 5. Jeff can choose several cards and ...
- POJ1769(线段树+DP)
飞翔 题意 : 给定一个区间长度 n ,接下来给出 m 个子区间,要求最少选出多少个区间才能使得 1~n 这个区间被所选的所有子区间覆盖 分析: 首先是动态规划,dp[i]表示把最大值从1位置搞到第i ...
- Photoshop入门教程(五):滤镜
学习心得:滤镜通常用于摄影行业,是安装在相机镜头前用于过滤自然光的附加镜头,从而获得一些特殊的效果.同理,Photoshop的滤镜也是为了产生特殊的效果.Photoshop滤镜分为两类:一种是内部滤镜 ...
- spring boot http2
项目已启动的情况下,启动单元测试报端口has binded 可以使用server.port=-1 禁用端口绑定来启动单元测试 https://docs.spring.io/spring-boot/do ...
- Problem02 输出素数
题目:判断101-200之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数. public class ...
- mysql 操作数据库创建,增删改查
创建数据库 默认字符编码 默认排序CREATE DATABASE IF NOT EXISTS day11 DEFAULT CHARSET utf8 COLLATE utf8_general_ci; / ...
- docker 命令详解(cp篇)
docker cp :用于容器与主机之间的数据拷贝. 1.从容器里面拷文件到宿主机 答:在宿主机里面执行以下命令 docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径 ...
- python groupby的小技巧
df.groupby('col',as_index=False),agg(ufunk)#as_index=False,可以消除层次索引 更多grouby的用法 http://blog.csdn.net ...
- listview适配器中的控件的点击事件并传值
@Override public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto ...