zoukankan      html  css  js  c++  java
  • 2048CODING

    年前用cocos2d实现了2048的鼠标手势识别,数字变换,得分记录以及卡片对象的大小位置颜色设置

     游戏基本思想:

    在原有游戏界面的基础上创建4*4的卡片排列矩阵并且存入一个二维数组,每个卡片对象内置数字初始化方法,包括设置数字,更改数字。

    卡片类头文件如下:

    #ifndef _2048_CardSprite_
    #define _2048_CardSprite_
    
    #include "cocos2d.h"
    
    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 *labTTFCardNumber;
    
        //显示的背景
        cocos2d::LayerColor *layerColorBG;
    };
    #endif // !

    各个方法的实现:

    #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;
    }
    
    bool CardSprite::init(){
        if (!Sprite::init())
        {
            return false;
        }
        return true;
    }
    
    
    //设置数字
    void CardSprite::setNumber(int num){
        number = num;
        //设置字体大小
        if (number >= 0){
            labTTFCardNumber->setFontSize(40);
        }
    
        if (number >= 16){
            labTTFCardNumber->setFontSize(35);
        }
        if (number >= 128){
            labTTFCardNumber->setFontSize(30);
        }
        if (number >= 1024){
            labTTFCardNumber->setFontSize(20);
        }
    
        //设置字体的颜色
        if (number == 0){
            labTTFCardNumber->setColor(cocos2d::Color3B(255, 222, 173));
        }
        if (number == 2){
            labTTFCardNumber->setColor(cocos2d::Color3B(176, 196, 222));
        }
        if (number == 4){
            labTTFCardNumber->setColor(cocos2d::Color3B(100, 149, 237));
        }
        if (number == 8){
            labTTFCardNumber->setColor(cocos2d::Color3B(0, 0, 255));
        }
        if (number == 16){
            labTTFCardNumber->setColor(cocos2d::Color3B(102, 205, 170));
        }
        if (number == 32){
            labTTFCardNumber->setColor(cocos2d::Color3B(124, 252, 0));
        }
        if (number == 64){
            labTTFCardNumber->setColor(cocos2d::Color3B(0, 255, 0));
        }
        if (number == 128){
            labTTFCardNumber->setColor(cocos2d::Color3B(0, 250, 154));
        }
        if (number == 256){
            labTTFCardNumber->setColor(cocos2d::Color3B(138, 43, 226));
        }
        if (number == 512){
            labTTFCardNumber->setColor(cocos2d::Color3B(255, 165, 0));
        }
        if (number == 1024){
            labTTFCardNumber->setColor(cocos2d::Color3B(255, 114, 86));
        }
        if (number == 2048){
            labTTFCardNumber->setColor(cocos2d::Color3B(139, 0, 0));
        }
        if (number == 4096){
            labTTFCardNumber->setColor(cocos2d::Color3B(130, 130, 130));
        }
        if (number == 8192){
            labTTFCardNumber->setColor(cocos2d::Color3B(255, 250, 250));
        }
    
        //更新显示的数字
    
        if (number > 0){
            labTTFCardNumber->setString(__String::createWithFormat("%i", number)->getCString());
        }
        else{
            labTTFCardNumber->setString("");
    
        }
    
    }
    
    //获取数字
    int CardSprite::getNumber(){
        return number;
    }
    
    void CardSprite::enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY){
        //初始化数字
        number = numbers;
    
        //加入游戏卡片的背景颜色
    
        layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(202, 255, 112, 255), width - 3, height - 3);
        layerColorBG->setPosition(Point(CardSpriteX, CardSpriteY));
    
    
        //判断如果不等于0就显示,否则为空
    
        if (number > 0)
        {
            //加入中间字体
            labTTFCardNumber = cocos2d::LabelTTF::create(__String::createWithFormat("%i", number)->getCString(), "Arial", 15);
            labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width / 2, layerColorBG->getContentSize().height/2));
            layerColorBG->addChild(labTTFCardNumber);
        }
        else{
            labTTFCardNumber = cocos2d::LabelTTF::create("", "Arial", 15);
            labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width / 2, layerColorBG->getContentSize().height / 2));
            layerColorBG->addChild(labTTFCardNumber);
        }
    
        this->addChild(layerColorBG);
    
    }

    由此可见,每个卡片对象的表现形式就是背景颜色。。。。

    在游戏主界面创建卡片的方法:

    void HelloWorld::createCardSprite(cocos2d::Size size){
        //求出单元格的宽度跟高度
    
        int lon = (size.width - 60) / 4;
    
        //4*4的单元格
    
        for (int j = 0; j < 4; j++)
            for (int i = 0; i < 4; i++)
            {
                CardSprite * card = CardSprite::createCardSprite(0, lon, lon, lon*j + 110, lon*i+ size.height / 12-10);
                addChild(card);
                //加到数组里
                cardArr[j][i] = card;
            }
    }

    鼠标手势的识别:

    bool HelloWorld::onTouchBegan(cocos2d::CCTouch *touch, cocos2d::Event *unused_event){
        Point touchPO = touch->getLocation();
    
    
        firstX = touchPO.x;
        firstY = touchPO.y;
    
    
    
        return true;
    }
    
    
    
    void HelloWorld::onTouchEnded(cocos2d::CCTouch *touch, cocos2d::Event *unused_event){
        Point touchPO = touch->getLocation();
    
    
        endX = firstX - touchPO.x;
        endY = firstY - touchPO.y;
    
        if (abs(endX) > abs(endY))
        {
            //左右
            if (endX + 5 < 0){        //5的偏移分量一般很小,防止误识别的话尽量往大的方向设置!!!
                if (doRight()){
                    autoCreateCardNumber();
                    //doCheckGameOver();
                }
            }
            else{
                if (doLeft()){
                    autoCreateCardNumber();
                    //doCheckGameOver();
                }
            }
    
        }
        else{
            //上下
            if (endY + 5 < 0){
                if (doUp()){
                    autoCreateCardNumber();
                    //doCheckGameOver();
                }
            }
            else{
                if (doDown()){
                    autoCreateCardNumber();
                    //doCheckGameOver();
                }
            }
        }
    }


    //监听事件的绑定:

    //监听事件绑定
    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
    touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

     

    2048主算法(左移):

    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){
                        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[x1][y]->getNumber() * 2);
                            cardArr[x1][y]->setNumber(0);
                            //设置分数
    
                            score += cardArr[x][y]->getNumber();
                            labTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
    
                            isDo = true;
    
                        }
                        break;
                    }
                }
            }
        }
        return isDo;
    }

    算法分析:当识别手势执行相应方法后:从第一排第一列c1开始遍历,观察c1右边的卡片c2是否有数字,有的话进入下一层判断,如果两个数字相同,c2归零,c1乘2,如果c1没有数字,c1设置为c2,c2归零,c1的位置还要左移一位,当然还有不相同但都有数字的情况,暂且搁一边。除了相同的数字合并外,c1都要左移,且跳出这个循环,从下一个卡片再开始判断,由于c1左移,所以又从原来的卡片位置开始判断,原来c2的位置已归零,所以内层循环起作用c2右移,所以就遍历了c1右边的所有卡片,只要合并过一次或移动到头一次,就会跳入第一排第二列c2的判断循环,方法如上,这就解释了当数字不同的时候,要么有一个数字是合并过的,另一个就该在此处,或是两个都没合并过,一起移动到最左。其它三个方法也是一样的思想,只不过方向不同。。。。

    最后游戏bug和疑问:1.每个行为方法里面的x--和break语句仔细考虑后净是为了减少运算量,,。。。。。

                                 2.由于没有设置随机种子,每次自动生成的数字在游戏前期貌似都是相同的位置,特别是开始的时候只有两个固定的位置。。。。- -

  • 相关阅读:
    【Python学习之路】——Day20(Django 上)
    【Python学习之路】——WEB本质
    【Python学习之路】——Day16(JavaScript)
    【Python学习之路】——Day14(HTML)
    【Python学习之路】——Day13(Redis and Memcached)
    【Python学习之路】——Day12(python mysql)
    【Python学习之路】——Day11(I/O多路复用)
    【Python学习之路】——Day10(线程、进程)
    【Python学习之路】——Day9(网络编程socket)
    哲学家就餐-同步问题解析-python
  • 原文地址:https://www.cnblogs.com/jokerspace/p/6438774.html
Copyright © 2011-2022 走看看