首页 > 代码库 > Cocos2dx制作2048(3.数字相加逻辑)
Cocos2dx制作2048(3.数字相加逻辑)
这次我们来完成整个2048的数字相加逻辑其实2048玩起来简单,做起来也简单,复杂就复杂在这整个游戏的逻辑。
1.分析向左滑动
第一轮相加步骤:
1. 单1+单2 单1=2 单2赋值为0 (单1为空,可以加任何数字)
2. 单1+单3 单1=4 单3赋值为0 (单1不为空,只能加和他相同的数字)
3. 单1+单4 单1=4 单4不变 (单1不为空,只能加和他相同的数字)
1. 单1+单2 单1=2 单2赋值为0 (单1为空,可以加任何数字)
2. 单1+单3 单1=4 单3赋值为0 (单1不为空,只能加和他相同的数字)
3. 单1+单4 单1=4 单4不变 (单1不为空,只能加和他相同的数字)
第二轮相加步骤:
1. 单2+单3 单2=0 单3不变 (单2为0可以加任何数字,但是单3也是0,,其实加不加都是一个效果)
2. 单2+单4 单2=2 单4赋值0 (单2为0可以加任何数字)
接着就是单3加单4了,这两个都为空,什么都不做,最终的效果也就是,第二轮相加后的效果了
这个其实就是用的冒泡算法,好了,理解了之后,那么我们来写代码。
首先,我们在初始化矩阵中给所有的数字方块初始化为2,暂时先注释掉随机创建的方法
void HelloWorld::initMatrix(CCSize size) { //两个方块之间的空隙 int space=10; int SquareSize=(size.width-space*5)/4; for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { float pointx=space+x*SquareSize+x*space; float pointy=40+y*SquareSize+y*space; SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(2,pointx,pointy,SquareSize,SquareSize); this->addChild(pSquareSprite,1); m_squarearray[x][y]=pSquareSprite; } } /* //刚开始游戏,创建两个方块 autoSquare(); autoSquare(); */ }
OK,向左滑动,那么此时我们需要在doLeft方法中写代码咯
bool HelloWorld::doLeft() { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int afterx = x+1; afterx < 4; afterx++) { } } } return true; }
大概的框架就是这样子吧??最外层的y我们可以忽视,这是左加不是上下加
里面两个循环表示什么呢??x=0时 afterx=1 即单1和单2 依次类推
OK,我们在循环中写代码,
bool HelloWorld::doLeft() { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int afterx = x+1; afterx < 4; afterx++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); } } } } return true; }
这里有两种情况,
1.单1等于0时,不管单2是什么,都要和单2调换位置
2.单1不等于0时,那么只有单1和单2相等,才能相加
大家可以运行看看效果。
2.分析向右滑动
这里和向左滑动差不多,其实就是一个是顺着来一个是倒着来,我就不画图了,直接上代码
bool HelloWorld::doReight() { for (int y = 0; y < 4; y++) { for (int x = 3; x >=0; x--) { for (int afterx = x-1; afterx >=0; afterx--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); } } } } return true; }
其他地方都没改,就把两个循环改了一下
3.分析向上滑动
bool HelloWorld::doTop() { for (int x = 0; x < 4; x++) { for (int y = 3; y >=0; y--) { for (int aftery = y-1; aftery >=0; aftery--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); } } } } return true; }
4.分析向下滑动
bool HelloWorld::doDown() { for (int x = 0; x < 4; x++) { for (int y = 0; y <4; y++) { for (int aftery = y+1; aftery <4; aftery++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); } } } } return true; }
现在基本上成了,那么我再修改其他几个函数,
首先把初始化矩阵的方法还原
void HelloWorld::initMatrix(CCSize size) { //两个方块之间的空隙 int space=10; int SquareSize=(size.width-space*5)/4; for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { float pointx=space+x*SquareSize+x*space; float pointy=40+y*SquareSize+y*space; SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize); this->addChild(pSquareSprite,1); m_squarearray[x][y]=pSquareSprite; } } //刚开始游戏,创建两个方块 autoSquare(); autoSquare(); }
然后,不管用户向那个方向滑动,只要是滑动了,就都得产生一个数字方块
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { bool isTouch=false; CCPoint point= pTouch->getLocation(); m_RangeX=m_StartX-point.x; m_RangeY=m_StartY-point.y; if (abs(m_RangeX)>abs(m_RangeY)) { //X大于Y 左右移动 if (m_RangeX>5) { //正数 向左 isTouch=doLeft(); } else if(m_RangeX<-5) { //负数 向右 isTouch=doReight(); } } else { //否则 上下移动 if (m_RangeY>5) { //正数 向下 isTouch=doDown(); } else if(m_RangeY<-5) { //负数 向上 isTouch=doTop(); } } if (isTouch) { autoSquare(); } }
测试一下,貌似我有发现了一个BUG
结合我们的代码分析一下也确实是这种情况,那么怎么破呢??
应该在两个同等数字相加后,就Brack,不能再继续加下去了
else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); break; }
刚测试,又发现一个BUG
本来是 4 2 4 0
向右滑动应该是 0 4 2 4
结果是: 0 0 2 8
大家结合doReight,在看看,好像也是这么回事
那么又应该怎么修复呢??
这里还不能再第一个IF加break
不然 2 2 2 0 就会变为 0 2 2 2了 而不是 0 0 2 4
这是一个很纠结的问题
我们应该要循环遍历一下 两个数字的中间是不是还有数字隔着,有就不加,没有就加
这里贴上所有逻辑代码
bool HelloWorld::doTop() { for (int x = 0; x < 4; x++) { for (int y = 3; y >=0; y--) { for (int aftery = y-1; aftery >=0; aftery--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = aftery+1; temp < y; temp++) { if (m_squarearray[x][temp]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); break; } } } } return true; } bool HelloWorld::doDown() { for (int x = 0; x < 4; x++) { for (int y = 0; y <4; y++) { for (int aftery = y+1; aftery <4; aftery++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = y+1; temp < aftery; temp++) { if (m_squarearray[x][temp]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); break; } } } } return true; } bool HelloWorld::doReight() { for (int y = 0; y < 4; y++) { for (int x = 3; x >=0; x--) { for (int afterx = x-1; afterx >=0; afterx--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = afterx+1; temp < x; temp++) { if (m_squarearray[temp][y]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); break; } } } } return true; } bool HelloWorld::doLeft() { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int afterx = x+1; afterx < 4; afterx++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = x+1; temp < afterx; temp++) { if (m_squarearray[temp][y]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); break; } } } } return true; }
5.为游戏增加动画效果
最后在来点,动画效果这里,动画就是,在创建一个数字方块的时候他是慢慢放大的,
我们的数字方块是什么??CCLayerColor
我也不知道为什么,我们之间这样
m_squarearray[x][y]->runAction(CCSequence::create(CCScaleTo::create(0,0,0),CCScaleTo::create(0.3f,1,1),NULL));
出现的效果并不理想。
那么我们就在SquareSprite中提供一个接口用来获得 m_layercolor
然后在用m_layercolor来执行动画
CCLayerColor* SquareSprite::getCClayerColor() { return this->m_layercolor; }
void HelloWorld::autoSquare() { int x=CCRANDOM_0_1()*4; int y=CCRANDOM_0_1()*4; if (m_squarearray[x][y]->getNumber()>0) { autoSquare(); } else { m_squarearray[x][y]->setNumber(2); m_squarearray[x][y]->getCClayerColor()->runAction(CCSequence::create(CCScaleTo::create(0,0,0),CCScaleTo::create(0.3f,1,1),NULL)); } }
6.附源码
SquareSprite.h
#ifndef _SQUARE_SPRITE_H_ #define _SQUARE_SPRITE_H_ #include "cocos2d.h" using namespace cocos2d; class SquareSprite:public CCSprite { public: SquareSprite(); static SquareSprite* createSquareSprite(int number,float pointx,float pointy,int width,int height); int getNumber(); void setNumber(int number); CCLayerColor* getCClayerColor(); CREATE_FUNC(SquareSprite); private: int m_number; CCLabelTTF* m_lablenumber; CCLayerColor* m_layercolor; void initSquareSprite(int number,float pointx,float pointy,int width,int height); }; #endif // !_SQUARE_SPRITE_H_
SquareSprite.cpp
#include "SquareSprite.h" SquareSprite::SquareSprite() :m_number(0) ,m_lablenumber(NULL) ,m_layercolor(NULL) { } SquareSprite* SquareSprite::createSquareSprite(int number,float pointx,float pointy,int width,int height) { SquareSprite *pSprite = new SquareSprite(); if (pSprite && pSprite->init()) { pSprite->autorelease(); pSprite->initSquareSprite( number, pointx, pointy, width, height); return pSprite; } CC_SAFE_DELETE(pSprite); return NULL; } int SquareSprite::getNumber() { return m_number; } void SquareSprite::setNumber(int number) { m_number=number; m_lablenumber->setString(""); m_layercolor->setColor(ccc3(200,190,180)); if (m_number>0) { m_lablenumber->setString(CCString::createWithFormat("%i",m_number)->getCString()); //设置卡片颜色 switch (m_number) { case 2: m_layercolor->setColor(ccc3(255,245,238)); break; case 32: case 4: m_layercolor->setColor(ccc3(255,0,0)); break; case 8: m_layercolor->setColor(ccc3(244,164,96)); break; case 16: m_layercolor->setColor(ccc3(255,69,0)); break; case 64: m_layercolor->setColor(ccc3(250,128,114)); break; case 128: m_layercolor->setColor(ccc3(255,228,181)); break; case 256: m_layercolor->setColor(ccc3(240,230,140)); break; case 512: m_layercolor->setColor(ccc3(255,250,205)); break; case 1024: m_layercolor->setColor(ccc3(255,160,122)); break; case 2048: m_layercolor->setColor(ccc3(250,240,230)); break; case 4096: m_layercolor->setColor(ccc3(255,228,225)); break; case 8192: m_layercolor->setColor(ccc3(188,143,143)); break; case 16384: m_layercolor->setColor(ccc3(205,92,92)); break; default: break; } } } void SquareSprite::initSquareSprite(int number,float pointx,float pointy,int width,int height) { m_number=number; m_layercolor=CCLayerColor::create(ccc4(200,190,180,255),width,height); m_layercolor->setPosition(ccp(pointx,pointy)); this->addChild(m_layercolor); //创建字体 m_lablenumber=CCLabelTTF::create("","arial.ttf",30); m_lablenumber->setColor(ccc3(0,0,0)); m_lablenumber->setPosition(ccp(m_layercolor->getContentSize().width/2,m_layercolor->getContentSize().height/2)); m_layercolor->addChild(m_lablenumber); setNumber(number); } CCLayerColor* SquareSprite::getCClayerColor() { return this->m_layercolor; }
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "SimpleAudioEngine.h" #include "SquareSprite.h" using namespace CocosDenshion; using namespace cocos2d; class HelloWorld : public cocos2d::CCLayer { public: HelloWorld(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); public: virtual void onEnter(); virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); //上下左右滑动时调用 bool doTop(); bool doDown(); bool doReight(); bool doLeft(); //初始化矩阵 void initMatrix(CCSize size); //随机产生方块 void autoSquare(); private: //启点的X坐标,Y坐标 //起点到终点X的距离,Y的距离 int m_StartX,m_StartY,m_RangeX,m_RangeY; //二维数组存储方块 SquareSprite* m_squarearray[4][4]; }; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h" USING_NS_CC; HelloWorld::HelloWorld() :m_StartX(0) ,m_StartY(0) ,m_RangeX(0) ,m_RangeY(0) { } CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); initMatrix(visibleSize); //搞点背景 CCLayerColor* layerColorBG= CCLayerColor::create(ccc4(180,170,160,255)); this->addChild(layerColorBG,0); return true; } void HelloWorld::initMatrix(CCSize size) { //两个方块之间的空隙 int space=10; int SquareSize=(size.width-space*5)/4; for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { float pointx=space+x*SquareSize+x*space; float pointy=40+y*SquareSize+y*space; SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize); this->addChild(pSquareSprite,1); m_squarearray[x][y]=pSquareSprite; } } //刚开始游戏,创建两个方块 autoSquare(); autoSquare(); } void HelloWorld::autoSquare() { int x=CCRANDOM_0_1()*4; int y=CCRANDOM_0_1()*4; if (m_squarearray[x][y]->getNumber()>0) { autoSquare(); } else { m_squarearray[x][y]->setNumber(2); m_squarearray[x][y]->getCClayerColor()->runAction(CCSequence::create(CCScaleTo::create(0,0,0),CCScaleTo::create(0.3f,1,1),NULL)); } } void HelloWorld::onEnter() { CCLayer::onEnter(); this->setTouchMode(kCCTouchesOneByOne); this->setTouchEnabled(true); } bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { m_StartX=pTouch->getLocation().x; m_StartY=pTouch->getLocation().y; return true; } void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { bool isTouch=false; CCPoint point= pTouch->getLocation(); m_RangeX=m_StartX-point.x; m_RangeY=m_StartY-point.y; if (abs(m_RangeX)>abs(m_RangeY)) { //X大于Y 左右移动 if (m_RangeX>5) { //正数 向左 isTouch=doLeft(); } else if(m_RangeX<-5) { //负数 向右 isTouch=doReight(); } } else { //否则 上下移动 if (m_RangeY>5) { //正数 向下 isTouch=doDown(); } else if(m_RangeY<-5) { //负数 向上 isTouch=doTop(); } } if (isTouch) { autoSquare(); } } bool HelloWorld::doTop() { for (int x = 0; x < 4; x++) { for (int y = 3; y >=0; y--) { for (int aftery = y-1; aftery >=0; aftery--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = aftery+1; temp < y; temp++) { if (m_squarearray[x][temp]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); break; } } } } return true; } bool HelloWorld::doDown() { for (int x = 0; x < 4; x++) { for (int y = 0; y <4; y++) { for (int aftery = y+1; aftery <4; aftery++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[x][aftery]->getNumber()); m_squarearray[x][aftery]->setNumber(0); } else if (m_squarearray[x][aftery]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = y+1; temp < aftery; temp++) { if (m_squarearray[x][temp]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[x][aftery]->setNumber(0); break; } } } } return true; } bool HelloWorld::doReight() { for (int y = 0; y < 4; y++) { for (int x = 3; x >=0; x--) { for (int afterx = x-1; afterx >=0; afterx--) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = afterx+1; temp < x; temp++) { if (m_squarearray[temp][y]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); break; } } } } return true; } bool HelloWorld::doLeft() { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int afterx = x+1; afterx < 4; afterx++) { if (m_squarearray[x][y]->getNumber()==0) { m_squarearray[x][y]->setNumber(m_squarearray[afterx][y]->getNumber()); m_squarearray[afterx][y]->setNumber(0); } else if (m_squarearray[afterx][y]->getNumber()==m_squarearray[x][y]->getNumber()) { bool isAdd=false; for (int temp = x+1; temp < afterx; temp++) { if (m_squarearray[temp][y]->getNumber()!=0) { isAdd=true; break; } } if (isAdd) { continue; } m_squarearray[x][y]->setNumber(m_squarearray[x][y]->getNumber()*2); m_squarearray[afterx][y]->setNumber(0); break; } } } } return true; }
最终效果图:
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。