2048的开发设计

2048主要是对方块的操作,所以我们最好封装一个方块类

新建头文件CardSprite.h,代码如下:


#ifndef __CARDSPRITE_SCENE_H__
#define __CARDSPRITE_SCENE_H__
 
#include "cocos2d.h"
 
class CardSprite : public cocos2d::Sprite
{
public:
    //初始化的数值,宽度,高度,卡片X轴,卡片Y轴
    static CardSprite* createCardSprite(int numbers,int width,int height,float CardSpriteX,float CardSpriteY);
    virtual bool init();
    CREATE_FUNC(CardSprite);
 
    //获取数字
    int getNumber();
    //设置数字
    void setNumber(int num);
 
private:
    //显示在界面中的数字
    int number;
    void enemyInit(int numbers,int width,int height,float CardSpriteX,float CardSpriteY);
 
    //定义显示数字的控件
    cocos2d::LabelTTF* labelTTFCardNumber;
 
    //显示背景
    cocos2d::LayerColor* layerColorBG;
};
 
#endif // __CARDSPRITE_SCENE_H__

CardSprite.cpp

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

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;
 
    //加入游戏的背景颜色
    layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(200,190,180,255),width-15,height-15);
    layerColorBG->setPosition(Point(CardSpriteX,CardSpriteY));
 
    //判断如果大于0就显示,否则显示空
    if(number > 0)
    {
        //加入中间字体
        labelTTFCardNumber = LabelTTF::create(String::createWithFormat("%i",number)->getCString(),"HiraKakuProN-W6",100);
        labelTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2,layerColorBG->getContentSize().height/2));
        labelTTFCardNumber->setTag(8);
        layerColorBG->addChild(labelTTFCardNumber);
    }
    else
    {
        //加入中间字体
        labelTTFCardNumber = LabelTTF::create("","HiraKakuProN-W6",100);
        labelTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2,layerColorBG->getContentSize().height/2));
        labelTTFCardNumber->setTag(8);
        layerColorBG->addChild(labelTTFCardNumber);
    }
 
    this->addChild(layerColorBG);
}

//获取数字
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("");
    }
    
  //判断数字的大小来调整字体
    if (number >= 0) {
        labelTTFCardNumber->setFontSize(100);
    }
    if (number >= 16) {
        labelTTFCardNumber->setFontSize(90);
    }
    if(number >= 128){
        labelTTFCardNumber->setFontSize(60);
    }
    if(number >= 1024){
        labelTTFCardNumber->setFontSize(40);
    }
    
//判断数字的大小来调整颜色
    if(number == 0){
        layerColorBG->setColor(cocos2d::Color3B(200,190,180));
    }
    if (number == 2) {
        layerColorBG->setColor(cocos2d::Color3B(240,230,220));
    }
    if (number == 4) {
        layerColorBG->setColor(cocos2d::Color3B(240,220,200));
    }
    if (number == 8) {
        layerColorBG->setColor(cocos2d::Color3B(240,180,120));
    }
    if (number == 16) {
        layerColorBG->setColor(cocos2d::Color3B(240,140,90));
    }
    if (number == 32) {
        layerColorBG->setColor(cocos2d::Color3B(240,120,90));
    }
    if (number == 64) {
        layerColorBG->setColor(cocos2d::Color3B(240,90,60));
    }
    if (number == 128) {
        layerColorBG->setColor(cocos2d::Color3B(240,90,60));
    }
    if (number == 256) {
        layerColorBG->setColor(cocos2d::Color3B(240,200,70));
    }
    if (number == 512) {
        layerColorBG->setColor(cocos2d::Color3B(240,200,70));
    }
    if (number == 1024) {
        layerColorBG->setColor(cocos2d::Color3B(0,130,0));
    }
    if (number == 2048) {
        layerColorBG->setColor(cocos2d::Color3B(0,130,0));
    }

}





这个类的主要功能是创建卡片以及给卡片设置属性,也就是卡片的数字以及数字大小、颜色。
有了卡片类,下面就把卡片加入到界面GameScene上:
GameScene.h
//创建一个卡片二位数组
CardSprite* cardArr[4][4];
//创建卡片
void createCardSprite(cocos2d::Size size);
//自动生成卡片
void autoCreateCardNumber();


GameScene.cpp
在init()函数中:
Size visibleSize = Director::getInstance()->getVisibleSize();
//创建卡片
createCardSprite(visibleSize);
//加入游戏的背景颜色
auto layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(180,170,160,255));
this->addChild(layerColorBG);
//在游戏刚开始的时候,创建两个卡片,所以调用两次这个函数创建2张自动生成卡片
autoCreateCardNumber();
autoCreateCardNumber();
//判断游戏是否还能继续
void doCheckGameOver();

//滑向上下左右的方法
    bool doUp();
    bool doDown();
    bool doLeft();
    bool doRight();
//点击元素
int firstX,firstY,endX,endY;
//触摸监听
auto touchListener=EventListenerTouchOneByOne::create();
touchListener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
touchListener->onTouchEnded=CC_CALLBACK_2(HelloWorld::onTouchEnded,this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener,this);







//创建卡片
void GameScene::createCardSprite(cocos2d::Size size)
{
    //求出单元格的宽度和高度
    int unitSize = (size.height-28)/4;
 
    //4*4的单元格
    for(int i=0; i<4; i++)
    {
        for(int j=0; j<4; j++)
        {
          //最后两个参数,需要根据手机屏幕进行适配。
          CardSprite* card = CardSprite::createCardSprite(2, unitSize, unitSize, unitSize*i+140, unitSize*j+20);
          addChild(card);
	//把卡片加入到数组中
	cardArr[i][j] = card;

        }
    }
}

//自动生成卡片
void GameScene::autoCreateCardNumber()
{
    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 ? 2: 4);
    }
}


卡片已经加入到界面中,然后就是游戏的算法逻辑,因为该游戏根据手势滑动来处理,所以逻辑的处理都应在触摸事件中:
向左滑动函数的逻辑代码:
bool GameScene::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) {
                    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[x][y]->getNumber() == cardArr[x1][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;
}

大概意思就是遍历所有方块,如果这个方块右边的方块不为空,则该方块会向左侧移动,如果右边的数等于左边的数,那么左边的数乘以2,然后把右边的数设置为0,也就变为了空。

向右滑动函数的逻辑代码:
bool GameScene::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[x][y]->getNumber() == cardArr[x1][y]->getNumber()){
                        cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
                        cardArr[x1][y]->setNumber(0);
                         
                        isdo = true;
                    }
                    break;
                }
            }
             
        }
    }
    return isdo;
}
向下滑动函数的逻辑代码:
bool GameScene::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][y]->getNumber() == cardArr[x][y1]->getNumber()){
                        cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
                        cardArr[x][y1]->setNumber(0);
                         
                        isdo = true;
                    }
                    break;
                }
            }
             
        }
    }
    return isdo;
}
向上滑动函数的逻辑代码:
bool GameScene::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][y]->getNumber() == cardArr[x][y1]->getNumber()){
                        cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
                        cardArr[x][y1]->setNumber(0);
                         
                        isdo = true;
                    }
                    break;
                }
            }
             
        }
    }
    return isdo;
}

//判断游戏是否还能继续 
//利用五个条件判断游戏是否还能够继续:(1)还有空卡片 (2)还可以向右滑 (3)还可以向左滑 (4)还可以向上滑 (5)还可以向下滑。
只要以上条件满足一个,游戏就可以再继续。否则,游戏就不能够再继续了,会重新回到开始的界面。

void GameScene::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) {
        //游戏结束,重新开始游戏
        log("游戏结束");
        Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
    }
}

//事件监听回调:触摸开始
bool GameScene::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
    //获取触摸的X轴和Y轴
    Point touchPoint = touch->getLocation(); //获取OpenGL坐标(即cocos2d-x坐标,原点在左下角)
    touch->getLocationInView();
    firstX=touchPoint.x;
    firstY=touchPoint.y;
 
    return true;
}
//事件监听回调:触摸结束
void GameScene::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
    //获取X轴和Y轴的移动范围
    Point touchPoint=touch->getLocation(); //获取OpenGL坐标(即cocos2d-x坐标,原点在左下角)
    endX=firstX - touchPoint.x;
    endY=firstY - touchPoint.y;
 
    //判断X轴和Y轴的移动距离,如果X轴的绝对值大,则向左右滑动,如果Y轴的绝对值大,则向上下滑动
    if(abs(endX) > abs(endY))
    {
        //手势向左右
        //判断向左还是向右
        if(endX+5>0)
        {
            //向左
            doleft();
	
        }
        else
        {
            //向右
            doRight();
        }
    }
    else
    {
        //手势向上下
        //判断手势向上还是向下
        if(endY+5>0)
        {
            //向下
            doDown();
        }
        else
        {
            //向上
            doUp();
        }
 
    }

//判断游戏是否还能继续
 doCheckGameOver();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值