基于cocos2d-x简易泡泡龙游戏二
歡迎大家轉載http://blog.csdn.net/demon_wu/article/details/9925663
上一章節是一個下午的功勞,做了基礎的界面和發射的功能,發射完了我們需要停止,停止是在兩種情況下,一是在頂層,一是碰撞到其他球的時候,所以需要添加一個函數來進行判斷的
bool MainLayer::checCollideBoard() {bool bRet = false;//判斷是否是頂層if (ready->getPosition().y > 960 -30){bRet = true;return bRet;}//檢驗是否與其他的泡泡發生碰撞for (int i = MAX_ROWS - 1; i >= 0; --i){for (int j = 0; j < MAX_COLS; ++ j){PaoPao *obj = board[i][j];//采取圓形碰撞檢驗if (obj && isCircleCollision(obj->getPosition(), 30.0, ready->getPosition(), 30.0)){bRet = true;break;}}if (bRet) break;}return bRet; } 同時需要在update里面移動完位置的時候進行此判斷,然后執行位置確認,因為我們如果現在停止,那么位置將不會是準確的位置,所以需要進行修改,修改完位置過后需要做的是判斷是否有可以消除的泡泡以及是否有可以掉落的泡泡,如果有的話執行相關操作。先添加update里面需要添加的代碼: void MainLayer::update(float fDelta) //update函數 {if (isCollideBorder()) //先判斷是否碰撞{real.x = -real.x; //如果碰撞就需要反方向移動}CCPoint pos = ready->getPosition(); //獲取當前發射的泡泡的位置ready->setPosition(ccp(pos.x + real.x * PAOPAO_SPEED, pos.y + real.y * PAOPAO_SPEED)); //設置泡泡的位置if (checCollideBoard()) //檢驗可以停止碰撞了{real = CCPointZero;correctReadyPosition(); //修正位置this->unscheduleUpdate(); //取消updatechangeWaitToReady(); //將等待使用的泡泡移動位置setEnable();return ;} }我們判斷可以停止過后先做修正位置,因為之前有一個函數是通過行、列和_flag來確定泡泡的位置,所以我采用了一個笨辦法來確認位置,就是遍歷所有的泡泡位置,哪一個位置與我當前位置最近并且沒有泡泡存在,那么我將泡泡移動過去,使用的效果還不錯。
//確認發射出去泡泡的位置 void MainLayer::correctReadyPosition() {int offX, offY;offX = 0;offY = 0;CCPoint pos = ready->getPosition();float length = FLT_MAX;bool flag = getFirstRowFlag(); //獲取第一行的flag值,雖然暫時沒有做下移,但是當增加下移的時候這個方法是需要的bool tempFlag = flag;for (int i = 0; i < MAX_ROWS; ++ i) //此方法可以優化,暫時先采取笨辦法{for (int j = 0; j < MAX_COLS; ++ j){if (!board[i][j]){CCPoint tPos = getPointByRowAndCol(i, j, flag);if (ccpDistance(tPos, pos) < length){offX = i;offY = j;tempFlag = flag;length = ccpDistance(tPos, pos);}}}flag = !flag;}//將ready數據轉換board[offX][offY] = ready;ready->setFlag(tempFlag);ready->setPosition(getPointByRowAndCol(offX, offY, tempFlag));ready = NULL;sameSum = 0;findTheSamePaoPao(offX, offY, tempFlag, board[offX][offY]->getType()); //檢查出所有相同的泡泡,并且執行消除動畫效果resetAllPass(); //初始化所有的pass,表示所有泡泡是不能到達checkDownPaoPao(); //檢驗出哪些泡泡是能夠到達的downPaoPao(); //對于不能到達的泡泡來說是可以掉落的 } 當確認泡泡停止的位置時候將ready也就是使用中的球球狀態設置為NULL,同時去查找出所有相同的泡泡,重點來了,對于泡泡龍游戲來說,只是根據我當前發射泡泡停的位置開始尋找出附近是否是有相同的泡泡,如果有相同的泡泡并且超過或等于三個的時候表示可以消除。一個泡泡與它相鄰的位置有六個,左、右、左上、右上、左下、右下,只要其中任何一個位置泡泡符合相同這個條件,那么我們需要通過那個位置泡泡以相同的方法去尋找,這正是用遞歸的好時候呀,代碼如下: void MainLayer::findTheSamePaoPao(int i, int j, bool flag, PAOPAO_TYPE type) {if (i < 0 || i >= MAX_ROWS || j < 0 || j >= MAX_COLS) //退出遞歸條件一:超出范圍{return ;}if (!board[i][j]) //退出遞歸條件二:該位置沒有泡泡{return ;}if (board[i][j]->getType() != type) //退出遞歸條件三:當前的類型不一樣{return ;}if (board[i][j]->getIsSame()) //退出遞歸條件三:當前已經判斷過是相同的{return;}//現在時符合條件的,將會進行遞歸調用/*首先將自己isSame設置為true,并且增加theSame從當前位置左上,右上,左下,右下,左,右六個方向進行尋找*/board[i][j]->setIsSame(true);++sameSum;//左上if (flag && j > 0 && i > 0) //當該行是最左的時候,要求不是第一個{findTheSamePaoPao(i - 1, j - 1, !flag, type);}else if (!flag && i > 0) //不是最左的時候只需要控制不是第一行{findTheSamePaoPao(i - 1, j, !flag, type);}//右上if (flag && i > 0) //當時最左的時候右上{findTheSamePaoPao(i - 1, j, !flag, type);}else if (!flag && i > 0 && j < MAX_COLS - 1) //當不是最左的時候右上{findTheSamePaoPao(i - 1, j + 1, !flag, type);}//左下if (flag && j > 0 && i < MAX_ROWS) //當該行是最左的時候,要求不是第一個{findTheSamePaoPao(i + 1, j - 1, !flag, type);}else if (!flag && i < MAX_ROWS) //不是最左的時候只需要控制不是第一行{findTheSamePaoPao(i + 1, j, !flag, type);}//右下if (flag && i < MAX_ROWS) //當時最左的時候右上{findTheSamePaoPao(i + 1, j, !flag, type);}else if (!flag && i < MAX_ROWS && j < MAX_COLS - 1) //當不是最左的時候右上{findTheSamePaoPao(i + 1, j + 1, !flag, type);}//左if (j > 0){findTheSamePaoPao(i, j - 1, flag, type);}//右if (j < MAX_COLS){findTheSamePaoPao(i, j + 1, flag, type);}//當找到三個以上的時候開始進行設置消除,如果沒有三個的時候將會還原if (sameSum >= 3){PaoPao *obj = board[i][j];paopaoAction(obj);board[i][j] = NULL;}else{board[i][j]->setIsSame(false);} } 上面說的六個方向是對于正常的泡泡,但是在邊界的泡泡需要采取判斷,判斷依據是通過flag和是否是第一個或者是最后一個等,找到泡泡后通過paopaoAction函數來給泡泡相應的動畫效果,執行完動畫后將其移除掉。當泡泡消除后將會使一些泡泡是孤立在一起的,也就是沒有懸掛點,這些泡泡是需要掉落的泡泡,當初想怎么判斷是否沒有懸掛點的時候走了彎路,我直接說出現在的思想,因為第一行的是不用判斷是否有懸掛點,因為他們就是初始的懸掛點,但是我們需要通過這些懸掛點找出有哪些是被懸掛的,現在假如這個泡泡是懸掛點,那么我們要判斷它左、右、左下、右下是否是有泡泡,有的話設置pass值為true,表示可以到達,也就是可以繼續作為懸掛點,因為使用循環一行一行找的話有一個問題,我從該行第一個找到最后一個的時候是通過自身來判斷的,但是有可能右邊一個是懸掛點,但是自己不是懸掛點,那么將會影響到判斷,所有采取了兩次遍歷,一次從第一個找到最后一個,一次是從最后找到第一個來解決。剛說的情況如下圖:
如果按照一次遍歷,左邊那個泡泡將不會被認為是懸掛點,所以需要從左到右兩次遍歷才可以的,其代碼如下:
void MainLayer::checkDownPaoPao() {for (int i = 0; i < MAX_COLS; ++ i) //設置好第一行關聯{if (board[0][i]) board[0][i]->setIsPass(true);}//通過第一行來設置下一行的鏈接情況for (int i = 0; i < MAX_ROWS; ++ i){//當該點符合條件的時候,因為從左到右判斷一次,再從右到左判斷一次/*當第一次的時候橫著只關心右邊,第二次的時候橫著只關心左邊剩下關心與自己相關的下面兩個*///第一次for (int j = 0; j < MAX_COLS; ++ j){if (board[i][j] && board[i][j]->getIsPass()){//右邊if (j < MAX_COLS - 1 && board[i][j + 1]) board[i][j + 1]->setIsPass(true);if (i < MAX_ROWS - 1){//左下if (board[i][j]->getFlag() && j > 0 && board[i + 1][j - 1]) board[i + 1][j - 1]->setIsPass(true);else if (!(board[i][j]->getFlag()) && board[i + 1][j]) board[i + 1][j]->setIsPass(true);//右下if (board[i][j]->getFlag() && board[i + 1][j]) board[i + 1][j]->setIsPass(true);else if (!(board[i][j]->getFlag()) && j < MAX_COLS - 1 && board[i + 1][j + 1]) board[i + 1][j + 1]->setIsPass(true);}}}//第二次for (int j = MAX_COLS - 1; j >= 0; -- j){if (board[i][j] && board[i][j]->getIsPass()){//左邊if (j > 0 && board[i][j - 1]) board[i][j - 1]->setIsPass(true);if (i < MAX_ROWS - 1){//左下if (board[i][j]->getFlag() && j > 0 && board[i + 1][j - 1]) board[i + 1][j - 1]->setIsPass(true);else if (!(board[i][j]->getFlag()) && board[i + 1][j]) board[i + 1][j]->setIsPass(true);//右下if (board[i][j]->getFlag() && board[i + 1][j]) board[i + 1][j]->setIsPass(true);else if (!(board[i][j]->getFlag()) && j < MAX_COLS - 1 && board[i + 1][j + 1]) board[i + 1][j + 1]->setIsPass(true);}}}} } 當找到所有可以到達點,就只需要知道哪些不可以到達,不可以到達就需要掉落動畫就可以了。源碼地址,VS版源碼地址源碼是完整的。
歡迎大家光臨。
總結
以上是生活随笔為你收集整理的基于cocos2d-x简易泡泡龙游戏二的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国大学MOOC消费者行为学考试题库(含
- 下一篇: VSC# ArcGIS 二次开发--出