阿J的cocos2d-x学习笔记-元素消消看(二)-主场景的创建

主场景的设计,核心是一个10x10的矩阵,从中我们可以实现同族消去。就如同popstar中那样。具体的算法参考了极客学院关于popstar的讲解。自己也做了许多改动。从功能上看,无需实现右边向左边靠拢,从具体实现上看,也做了较大改动。其中数据检测部分参考较多。原网站如下:http://www.jikexueyuan.com/course/60_1.html?ss=2

下面简单说下算法:

1初始化矩阵

随机生成数字1到118,分别对应元素。大于118的部分对应十字道具。

void challengeModel::autoCreateelementSprite(cocos2d::Size size)

{

    int maxX=125;

    int minX=1;

 

    int rangeX=maxX-minX;

    int actualX=0;

    elementSprite* element=new elementSprite();

    srand(((unsigned)time(NULL)));

 

    int lon=(size.width-28)/10;

    for(int j=0;j<10;j++)

    for(int i=0;i<10;i++)

    {

         actualX=(rand()%rangeX)+minX;

            if (actualX >=119)

               actualX = 119;

            element=elementSprite::createElementSprite(actualX,90, 90, lon*j+28 , lon*i+size.height/6+20 );

             element->setElementX(j);

             element->setElementY(i);

            element->setNumberAndGroup(actualX);

            element->setAnchorPoint(ccp(0,0));

            element->setPosition(lon*j + 28, lon*i +size.height / 6 + 20);

           //element->setElementSpriteX(lon*j);

           //element->setElementSpriteY(lon*i + size.height / 6);

 

            //Size sizeOfImage=element->getContentSize();

          

            element->setScale(0.75);

 

            addChild(element);

             elementSpriteMatrix[j][i]=element;

    }

}

2.检测相同的方块

(1)先检测一个方块上下左右的相同的方块,将其加入数组

(2)之后对数组中每一个方块进行迭代检测,并判断检测到的方块是否为新的方块,如果为新的就加入到数组中,如果不是就不加入。

cocos2d::__Array* challengeModel::checkElementUDLR(elementSprite* ele)

{

    cocos2d::__Array *arr = cocos2d::__Array::create();

 

    bool isDoubleGroup = false;

    //检测该位置以上的相同数目

    int up = ele->getElementY();

    for (int yu = up + 1; yu < 10; yu++)

    {

       if (elementSpriteMatrix[ele->getElementX()][yu]== NULL)break;

       if (elementSpriteMatrix[ele->getElementX()][yu]->getGroup()== elementSpriteMatrix[ele->getElementX()][up]->getGroup())

       {

           arr->addObject(elementSpriteMatrix[ele->getElementX()][yu]);

           isDoubleGroup = true;

       }

       else

           break;

    }

 

    int down = ele->getElementY();

    for (int yd = down - 1; yd >= 0; yd--)

    {

       if (elementSpriteMatrix[ele->getElementX()][yd]== NULL) break;

       if (elementSpriteMatrix[ele->getElementX()][yd]->getGroup()== elementSpriteMatrix[ele->getElementX()][down]->getGroup())

       {

           arr->addObject(elementSpriteMatrix[ele->getElementX()][yd]);

           isDoubleGroup = true;

       }

       else

           break;

    }

 

    int left = ele->getElementX();

    for (int xl = left - 1; xl >= 0; xl--)

    {

       if (elementSpriteMatrix[xl][ele->getElementY()] == NULL)break;

       if (elementSpriteMatrix[xl][ele->getElementY()]->getGroup() == elementSpriteMatrix[left][ele->getElementY()]->getGroup())

       {

           arr->addObject(elementSpriteMatrix[xl][ele->getElementY()]);

           isDoubleGroup = true;

       }

       else

           break;

    }

 

    int right = ele->getElementX();

    for (int xr = right+ 1; xr < 10; xr++)

    {

       if (elementSpriteMatrix[xr][ele->getElementY()] == NULL)break;

       if (elementSpriteMatrix[xr][ele->getElementY()]->getGroup() == elementSpriteMatrix[right][ele->getElementY()]->getGroup())

       {

           arr->addObject(elementSpriteMatrix[xr][ele->getElementY()]);

           isDoubleGroup = true;

       }

       else

           break;

    }

    arr->addObject(ele);

    return arr;

}

//检测该序列中是否有新的精灵,如果有的话

void challengeModel::checkElementISNEW(cocos2d::__Array *arrold)

{

    cocos2d::__Array *arrnew = cocos2d::__Array::create();

    for (int i = 0; i < arrold->count(); i++)

    {

       elementSprite* ele = (elementSprite*)arrold->getObjectAtIndex(i);

       cocos2d::__Array *arrnews = checkElementUDLR(ele);

       for (int j = 0; j < arrnews->count(); j++)

       {

           bool isSave = false;

           elementSprite* elenew = (elementSprite*)arrnews->getObjectAtIndex(j);

           for (int k = 0; k < elementarr->count(); k++)

           {

              elementSprite* eleold = (elementSprite*)arrold->getObjectAtIndex(k);

              if ((elenew->getElementX() == eleold->getElementX())&& (elenew->getElementY() == eleold->getElementY()))

              {

                  isSave = true;

                  break;

              }

           }

           if (!isSave)

           {

              arrnew->addObject(elenew);

           }

       }

    }

    if (arrnew->count()>0)

    {

       for (int q = 0; q < arrnew->count(); q++)

       {

           elementarr->addObject(arrnew->getObjectAtIndex(q));

       }

       checkElementISNEW(elementarr);

    }

    else

    {

       clearElementArr();

       calculateScore();

       reDissElement();

      

    }

}

3.上面元素相向下面移动

依次检测每列,从上到下移动。

对于每列而言,从上到下检测前面的空位,之后从上往下依次下沉

//上面的精灵向下填补空白

void challengeModel::reDissElement()

{

    for (int i = 0; i < 10; i++)

    {

       reDissElementRun(i);

    }

}

//每一列上面的精灵向下填补空白

void challengeModel::reDissElementRun(int x)

{

    int number = 0;

    int numberOfSpace[10] = {0};

   

    for (int i = 0; i < 10; i++)

    {

 

       if (elementSpriteMatrix[x][i]==NULL)

       {

           number++;

          

       }

       numberOfSpace[i] = number;

    }

   

       if (number>0)

       {

           for (int y = 0; y < 10; y++)

           {

             

              if ((numberOfSpace[y]>0)&&(elementSpriteMatrix[x][y] != NULL))

              {

                 

                     elementSprite* ele = elementSpriteMatrix[x][y];

                   ele->runAction(MoveTo::create(1, pointOfItem(x, y -numberOfSpace[y])));

                   elementSpriteMatrix[x][y - numberOfSpace[y]] = ele;

                   ele->setElementY(y - numberOfSpace[y]);

                 

                           

              }

             

              if (y >=(10 - number))

              {

                  elementSpriteMatrix[x][y] = NULL;

              }

           }

       }

   

 

}

4.分数的计算及十字道具的使用

暂时先这样,按照消去的数目加分。

int challengeModel::calculateScore()

{

    if (elementarr->count() < 2)

       return 0;

    else

    {

       switch (elementarr->count())

       {

       case 2:score = score + 3;

           break;

       case 3:score = score + 5;

           break;

       case 4:score = score + 7;

           break;

       case 5:score = score + 10;

       default:

           score = score + 10 + elementarr->count();

           break;

       }

    }

    updateScore();

    return score;

}

void challengeModel::clearCrossing(elementSprite* ele)

{

    for (int i = 0; i < 10; i++)

    {

       if (elementSpriteMatrix[ele->getElementX()][i] != NULL)

       {

           elementarr->addObject(elementSpriteMatrix[ele->getElementX()][i]);

       }

    }

    for (int i = 0; i < 10; i++)

    {

       if (elementSpriteMatrix[i][ele->getElementY()] != NULL)

       {

           elementarr->addObject(elementSpriteMatrix[i][ele->getElementY()]);

       }

    }

    elementarr->addObject(ele);

    clearElementArr();

    //calculateScore();

    calculateAddition();

   

}

5.检测是否游戏结束

主要是检测是否有同组的方块,isGameOver为游戏结束的标志,isLevelOver为关数结束的标志。其中很重要的一部分是进行场景的切换和关数的更新,这个部分在下一部分详细探讨。

bool challengeModel::reGameOver()

{

    bool isLevelOver = true;

    bool isGameOver = false;

    for (int i = 0; i < 10; i++)

    {

 

       for (int j = 0; j < 10; j++)

       {

           if (elementSpriteMatrix[i][j] != NULL && (checkElementUDLR(elementSpriteMatrix[i][j])->count()>1))

           {

              isLevelOver = false;

              break;

           }

       }

       if (isLevelOver == false)

           break;

    }

    if (isLevelOver)

    {

       if (score < goal)

           isGameOver = true;

       setScoreGoalLevelOfXml(score,goal+100,level+1);

       setFirstTime(false);

       auto director = Director::getInstance();

       director->replaceScene(challengeModel::createScene());

      

    }

    if (isGameOver)

    {

       setHeightestScore();

       setFirstTime(true);

       setScoreGoalLevelOfXml(0,100,1);

       auto director = Director::getInstance();

       director->replaceScene(menuScene::createScene());

    }

   

    return isGameOver;

}

6.关数的更新方法和数据的存储

(1)关数的更新:使用一bool型变量isFirstTime标示是否为第一关,如果是,初始化各个数据如goal、score和level为初始值。否则读取储存的各项数据,更新关数(level)。下面摘录其中一个函数。

(2)数据的存储,可以参考http://www.apkbus.com/android-142408-1-1.html一个关于打飞机的游戏。

bool challengeModel::setScoreGoalLevelOfXml(int score, int goal, int level)

{

    CCUserDefault::sharedUserDefault()->setIntegerForKey("score", score);

    CCUserDefault::sharedUserDefault()->setIntegerForKey("goal", goal);

    CCUserDefault::sharedUserDefault()->setIntegerForKey("level", level);

    CCUserDefault::sharedUserDefault()->flush();

    return true;

}

bool challengeModel::getScoreGoalLevelOfXml()

{

    if (isHaveSavedFile())

    {

       score = CCUserDefault::sharedUserDefault()->getIntegerForKey("score", 0);

       goal = CCUserDefault::sharedUserDefault()->getIntegerForKey("goal", 100);

       level = CCUserDefault::sharedUserDefault()->getIntegerForKey("level", 1);

       return true;

    }

    return false;

}

7.关于分享操作

现在sharesdk已经在这一方面做得很好,也是免费的。具体的集成方法在其官网上有详解,可以参考http://wiki.mob.com/cocos2d-x-3-x快速集成指南/

注意如果用的cocos2d版本为3.x,则参考上面网址,如果用的是2.x,则参考http://blog.csdn.net/song_hui_xiang/article/details/32131833

void shareResultHandler(C2DXResponseState state,C2DXPlatType platType, __Dictionary *shareInfo, __Dictionary *error)

    {

       CCLog("shareResultHandler");

        switch (state)

        {

            case C2DXResponseStateSuccess:

                C2DXShareSDK::toast("分享成功");

                break;

            case C2DXResponseStateFail:

                C2DXShareSDK::toast("分享失败");

                break;

            default:

                C2DXShareSDK::toast("分享取消");

                break;

        }

    }

    void challengeModel::shareMenuItemClick(CCObject* pSender)

    {

       __Dictionary *content = __Dictionary::create();

           //Dictionary可用的Key如下,如果需要用到其它字段,可自行参考Sample中的代码实现:

           // (并不是所有平台都有这些字段,需要参考文档http://wiki.mob.com/Android_%E4%B8%8D%E5%90%8C%E5%B9%B3%E5%8F%B0%E5%88%86%E4%BA%AB%E5%86%85%E5%AE%B9%E7%9A%84%E8%AF%A6%E7%BB%86%E8%AF%B4%E6%98%8E)

 

           content ->setObject(String::create("我在元素消消看中取得了不错的成绩,你敢来试一试吗?"), "content"); //要分享的内容,注意在文档中content对应的是text字段

         //  content ->setObject(String::create("http://img0.bdstatic.com/img/image/shouye/systsy-11927417755.jpg"),"image"); //可以是本地路径(如:/sdcard/a.jpg)或是一个URL

           content ->setObject(String::create("元素消消看"), "title");

          // content -> setObject(String::create("测试描述"), "description");

           //content ->setObject(String::create("http://sharesdk.cn"), "url");

          content ->setObject(String::createWithFormat("%d", C2DXContentTypeNews), "type");

           //content -> setObject(String::create("http://sharesdk.cn"),"siteUrl");

          // content ->setObject(String::create("ShareSDK"), "site");

          // content ->setObject(String::create("http://mp3.mwap8.com/destdir/Music/2009/20090601/ZuiXuanMinZuFeng20090601119.mp3"),"musicUrl");

           content ->setObject(String::create("extInfo"), "extInfo"); //微信分享应用时传给应用的附加信息

           C2DXShareSDK::showShareMenu(NULL,content, cocos2d::Point(100, 100), C2DXMenuArrowDirectionLeft, shareResultHandler);

         //C2DXShareSDK::showShareView(C2DXPlatTypeSinaWeibo,content, shareResultHandler);

    }

 

8.安卓监听返回键和菜单键及场景的切换

进行移动平台开发不能忘了监听返回键和菜单键

详细参考http://blog.csdn.net/we000636/article/details/8597540

而进行场景的操作,可以参考http://blog.csdn.net/tonny_guan/article/details/27570063

 

void challengeModel::onKeyReleased(EventKeyboard::KeyCodekeyCode, Event* event)

{    

    switch(keyCode)   

   {        

     case EventKeyboard::KeyCode::KEY_ESCAPE:

      setHeightestScore();

      Director::getInstance()->pushScene(menuScene::createScene());

          //Director::getInstance()->popScene();

           break;         //检测返回键

     case EventKeyboard::KeyCode::KEY_MENU:

      setHeightestScore();

           break;    

    }

}

9.小结

这里主要讲了游戏场景的搭建,代码可以从下面地址下载:http://download.csdn.net/download/u012483487/8463729


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值