1. 程式人生 > >cocos2d-x 3.4 之 三消類遊戲——萬聖大作戰(附加篇)

cocos2d-x 3.4 之 三消類遊戲——萬聖大作戰(附加篇)

***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************

三消遊戲——萬聖大作戰,應該是我最早的教程的教程之一了(總共也沒幾個o(╯□╰)o)

之前就簡單實現了 消除,四消這些;

釋出以來,很多人問我 爆炸 腫麼辦? 五消 腫麼辦??特效之間交換腫麼辦???

正好,這段時間找工作,在家呆著,有些時間,就把這個遊戲完善一下啦~

PS: 北京有木有 招cocos2d-x 實習生的= =。

好啦,好啦,說正事。

本文將會講述的內容:

—— 新增 兩種特效的產生(爆炸 and 五消(開心消消樂中的 魔力鳥)

—— 新增 兩種特效 消除時候的效果

—— 新增 特效之間交換 也會消除並觸發相應效果

—— 小修飾(觸控式螢幕蔽)

1. 新增兩種特效的產生

這裡,首先要總結一下之前的消除:


每個小方格都代表一個精靈,預設是同一個種類的,

—— 帶著小三角形的精靈,代表 交換的精靈

然後,總結下來:

① 普通的三消

② 普通的四消,產生 四消特效精靈

③ 普通的五消,產生 五消特效精靈

④、⑤ 變異的五消,產生 爆炸特效精靈

⑥、⑦ 變異的七消,⑥ 產生 五消精靈,⑦ 產生爆炸精靈

當產生上述形狀時,所有的精靈都會被消除~

還有,不全消除的情況嗎? of course(捉急的英語= =。)


①、② 這種 應該產生三消的情況下,凸出來的那個精靈,不應該被消除

③、④ 這種 應該產生四消的情況下,凸出來的那個精靈,不應該被消除

⑤、⑥、⑦ 這種 應該產生五消的情況下,凸出來的那個精靈,不應該被消除

總之,上面這些情況,凸出來的部分都不應該被消除。

這兩個圖,基本上涵蓋了所有情況( 把上面各種圖形 旋轉90°、180°、270° )

看出來規律了嗎?

什麼時候精靈會全部消除?———— 該行或該列 大於等於3!!

產生特效的順序呢?

>1  如果某行或某列個數 大於等於5  直接產生 五消特效 精靈

BUT,是否要消除 另外一個方向的所有精靈,就要看個數是否大於等於3了。

>2  如果某行或某列個數 大於等於4 

先判斷 交換精靈 的另一個方向精靈個數 是否大於等於3,

—— ≥3 則,產生爆炸特效精靈,並且全部消除

—— <3 則,產生四消特效精靈,只消除 ≥4 的那個方向的精靈

>3 如果 某行或某列的個數 大於等於3

判斷 交換精靈 另一個方向精靈個數 是否大於等於 3

—— ≥3 則,產生 爆炸特效精靈,並且全部消除

—— <3 則,普通三消,只消除≥3 那個方向的精靈

邏輯已經清楚了,我們就可以直接改程式碼了。

找到 GameScene.cpp :

checkAndRemove函式: 用來檢查並移除相應精靈

void GameScene::checkAndRemoveSprite()
{
	SpriteShape *spr;
    // 設定壽司的忽視檢查
	for( int r = 0 ; r < ROWS ; ++r )	{
		for( int c = 0 ; c < COLS ; ++c )	{
			spr = map[r][c];
			if( !spr )	{
				continue;
			}
			spr -> setIgnoreCheck(false);
		}
	}

	for( int r = 0 ; r < ROWS ; ++r )	{
		for( int c = 0 ; c < COLS ; ++c )	{
			spr = map[r][c];
			if( !spr )	{
				continue;
			}

			if( spr -> getIsNeedRemove() )	{
				continue;
			}

			// 新變化的特殊壽司,不消除
			if ( spr -> getIgnoreCheck() ) {
				continue;
			}
			
			removeAndPro(spr);
		}
	}

	// 3.消除標記了的壽司
	removeSprite();
}

removeAndPro函式: 查詢某個精靈 橫向 縱向個數,並且判斷是什麼樣的消除(其實也是為了避免checkAndRemove函式過長)

void GameScene::removeAndPro(SpriteShape *spr)
{
	// 獲取 橫豎 兩方向精靈
	std::list< SpriteShape *> colChainList;
	getColChain( spr , colChainList );

	std::list< SpriteShape *> rowChainList;
	getRowChain( spr , rowChainList );

	// 如果任意一方向的精靈都小於3個,直接return,不需要繼續往下看了
	if( rowChainList.size() < 3 && colChainList.size() < 3 )	{
		return;
	}

	CCLOG("row:%d,col:%d",rowChainList.size(),colChainList.size());

	// 判斷是交換產生的特效消除 還是 自由掉落 產生的特效消除
	bool isChangePro = false;

	if( rowChainList.size() >= 5 )	{
		// 兩方向精靈全部消除  並  產生五消除精靈(魔力鳥)
		if( colChainList.size() >= 3 )	{
			removeListSpr(rowChainList,true,DISPLAY_MODE_ANY,isChangePro);

			removeListSpr(colChainList,false,DISPLAY_MODE_ANY,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_ANY);
			}
		}   
		// 只消除 橫向 精靈 ,產生五消精靈
		else
		{
			removeListSpr(rowChainList,true,DISPLAY_MODE_ANY,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_ANY);
			}
		}

		return;
	}
	if( colChainList.size() >= 5 )	{
		if( rowChainList.size() >= 3 )	{
			// 兩方向精靈全部消除  並  產生五消除精靈(魔力鳥)
			removeListSpr(colChainList,true,DISPLAY_MODE_ANY,isChangePro);

			removeListSpr(rowChainList,false,DISPLAY_MODE_ANY,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_ANY);
			}
		}
		else
		{
			// 只消除 縱向 精靈 ,產生五消精靈
			removeListSpr(colChainList,true,DISPLAY_MODE_ANY,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_ANY);
			}
		}
		return;
	}


	if( rowChainList.size() >= 4 )	{
		if( colChainList.size() >= 3 )	{
			// 兩方向精靈都消除,產生爆炸精靈
			removeListSpr(rowChainList,true,DISPLAY_MODE_BOMB,isChangePro);

			removeListSpr(colChainList,false,DISPLAY_MODE_BOMB,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_BOMB);
			}
		}
		else
		{
			// 消除 橫向精靈,產生四消精靈
			removeListSpr(rowChainList,true,DISPLAY_MODE_VERTICAL,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_VERTICAL);
			}
		}
		return;
	}
	if( colChainList.size() >= 4 )	{
		if( rowChainList.size() >= 3 )	{
			// 兩方向精靈都消除,產生爆炸精靈
			removeListSpr(colChainList,true,DISPLAY_MODE_BOMB,isChangePro);

			removeListSpr(rowChainList,false,DISPLAY_MODE_BOMB,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_BOMB);
			}
		}
		else
		{
			// 消除 縱向精靈,產生四消精靈
			removeListSpr(colChainList,true,DISPLAY_MODE_HORIZONTAL,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_HORIZONTAL);
			}
		}
		return;
	}

	if( rowChainList.size() >= 3 )	{
		if( colChainList.size() >= 3 )	{
			// 兩方向精靈都消除,產生爆炸精靈
			removeListSpr(rowChainList,true,DISPLAY_MODE_BOMB,isChangePro);

			removeListSpr(colChainList,false,DISPLAY_MODE_BOMB,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_BOMB);
			}
		}
		else
		{
			// 消除橫向精靈
			removeListSpr(rowChainList,false,DISPLAY_MODE_BOMB,isChangePro);
		}
		return;
	}
	if( colChainList.size() >= 3 )	{
		if( rowChainList.size() >= 3 )	{
			removeListSpr(colChainList,true,DISPLAY_MODE_BOMB,isChangePro);

			removeListSpr(rowChainList,false,DISPLAY_MODE_BOMB,isChangePro);

			// 自由掉落產生
			if( isChangePro == false )	{
				spr->setIgnoreCheck(true);
				spr->setIsNeedRemove(false);
				spr->setDisplayMode(DISPLAY_MODE_BOMB);
			}
		}
		else
		{
			// 消除縱向精靈
			removeListSpr(colChainList,false,DISPLAY_MODE_BOMB,isChangePro);
		}
		return;
	}
}

removeListSpr函式:消除某個容器內所有精靈

// 移除某個容器的所有精靈
void GameScene::removeListSpr(std::list<SpriteShape *> &chainList,bool findSpe,DisplayMode dm,bool &isChangePro)
{
	// 遍歷用的迭代器
	std::list<SpriteShape *>::iterator itList;
	SpriteShape *sprite;

	for( itList = chainList.begin();itList != chainList.end();++itList ) {
		sprite = ( SpriteShape * )* itList;
		if( !sprite )	{
			continue;
		}

		if( findSpe )	{
			if ( sprite == staSprite || sprite == endSprite ) {
				isChangePro = true;
				// 如果交換消除的帶特效
				if( sprite->getDisplayMode() != DISPLAY_MODE_NORMAL )	{
					markRemove(sprite);
					sprite->setIsNeedRemove(false);
					sprite->setDisplayMode(dm);
				}
				else
				{
					sprite->setIgnoreCheck(true);
					sprite->setIsNeedRemove(false);
					sprite->setDisplayMode(dm);
				}
			}
		}
		markRemove( sprite );
	}
}

現在,所有的消除都能產生相應的消除特效了。

2.新增兩種特效消除的效果

在改動之前,一定要明確,消除的流程是什麼樣的:

> 接受觸控,交換精靈,遍歷陣列看是否有可以消除的精靈 checkAndRemove函式

> 檢視 精靈 應該如何消除(是否產生特效精靈),removeAndPro函式

> 標記應該消除的精靈,markRemove函式

> 所有都標記完後,執行消除函式,removeSprite函式

產生兩種特效的效果,主要在於 後面兩個 函式,

markRemove函式 與 removeSprite函式。

markRemove函式,是將 精靈 的消除屬性,置true,便於後面在removeSprite中判斷而執行消除。

在removeSprite中,遍歷所有的精靈,將消除屬性為 true 的,執行explodeSprite函式,播放動畫什麼的。

而且還要根據 它的型別(橫向或者縱向),執行特殊的動畫效果。

這次,爆炸和五消特效,我只執行了消除,並沒有像 開心消消樂 那種,還有動畫。

接下里是,程式碼部分:

markRemove函式

void GameScene::markRemove( SpriteShape* spr )
{
    if ( spr -> getIsNeedRemove()) {
        return;
    }
    if ( spr -> getIgnoreCheck() ) {
        return;
    }
    
    // 自己本身要消除
    spr -> setIsNeedRemove(true);
    // 檢視所需要消除的精靈是什麼型別的

	// 如果是 縱向消除 的精靈
    if ( spr ->getDisplayMode() == DISPLAY_MODE_VERTICAL) {
        for ( int r = 0; r < ROWS ; ++r ) {
			SpriteShape* tmp = map[r][spr->getCol()];
            if ( !tmp || tmp == spr ) {
                continue;
            }
            
            if (tmp->getDisplayMode() == DISPLAY_MODE_NORMAL) {
                tmp->setIsNeedRemove(true);
            } else {
                markRemove(tmp);
            }
        }
    // 如果消除的是 橫向消除特效 的精靈
    } 
	else if ( spr -> getDisplayMode() == DISPLAY_MODE_HORIZONTAL) {
        for (int c = 0; c < COLS ; ++c ) {
            SpriteShape *tmp = map[ spr -> getRow()][c];
            if (!tmp || tmp == spr) {
                continue;
            }
            
            if (tmp->getDisplayMode() == DISPLAY_MODE_NORMAL) {
                tmp->setIsNeedRemove(true);
            } else {
                markRemove(tmp);
            }
        }
    }
	// 消除的是 炸彈特效 的精靈
	else if( spr->getDisplayMode() == DISPLAY_MODE_BOMB )	{
		int dir[12][2] = {0,-2,-2,0,0,2,2,0,0,-1,-1,-1,-1,0,-1,1,0,1,1,1,1,0,1,-1};

		int tempX,tempY;
		for( int i = 0 ; i < 12 ; i++ )	{
			tempX = spr->getRow()+dir[i][0];
			tempY = spr->getCol()+dir[i][1];
			if( tempX >= 0 && tempX < ROWS && tempY >= 0 && tempY < COLS && map[tempX][tempY] )	{
				
				if (map[tempX][tempY]->getDisplayMode() == DISPLAY_MODE_NORMAL) {
					map[tempX][tempY]->setIsNeedRemove(true);
				} 
				else {
					markRemove(map[tempX][tempY]);
				}
			}
		}
	}
	// 消除的是 五消特效 的精靈
	else if( spr->getDisplayMode() == DISPLAY_MODE_ANY )	{
		// 如果是交換 執行 五消除
		if( staSprite && (staSprite->getDisplayMode()==DISPLAY_MODE_ANY || endSprite->getDisplayMode()==DISPLAY_MODE_ANY) )	{
			if( staSprite->getDisplayMode() == DISPLAY_MODE_ANY )	{
				for( int r = 0 ; r < ROWS ; r++ )	{
					for( int c = 0 ; c < COLS ; c++ )	{
						SpriteShape *tmp = map[r][c];
						if (!tmp || tmp == spr) {
							continue;
						}

						if( tmp->getImgIndex() == endSprite->getImgIndex() )	{
							if (tmp->getDisplayMode() == DISPLAY_MODE_NORMAL) {
								tmp->setIsNeedRemove(true);
							} 
							else {
								markRemove(tmp);
							}
						}
					}
				}
			}
			else
			{
				for( int r = 0 ; r < ROWS ; r++ )	{
					for( int c = 0 ; c < COLS ; c++ )	{
						SpriteShape *tmp = map[r][c];
						if (!tmp || tmp == spr) {
							continue;
						}

						if( tmp->getImgIndex() == staSprite->getImgIndex() )	{
							if (tmp->getDisplayMode() == DISPLAY_MODE_NORMAL) {
								tmp->setIsNeedRemove(true);
							} 
							else {
								markRemove(tmp);
							}
						}
					}
				}
			}
		}
		// 並非交換執行 五消除
		else
		{
			
			// 隨機消除某個
			int _rand = myRand_0_1()*(TOTAL_SP-1);

			for( int r = 0 ; r < ROWS ; r++ )	{
				for( int c = 0 ; c < COLS ; c++ )	{
					SpriteShape *tmp = map[r][c];
					if (!tmp || tmp == spr) {
						continue;
					}

					if( tmp->getImgIndex() == _rand )	{
						if (tmp->getDisplayMode() == DISPLAY_MODE_NORMAL) {
							tmp->setIsNeedRemove(true);
						} 
						else {
							markRemove(tmp);
						}
					}
				}
			}
			
		}
	}
}

注意到,裡面可能巢狀markRemove函式,因為,如果你消除一行的時候,那一行中恰好別的特效精靈,就將它扔進markRemove函式裡,一個簡單的遞迴。

在 觸發爆炸特效的時候,我是類似於以前做演算法 搜尋時候的習慣,把相對位置構成一個數組,然後直接遍歷就可以了。

在 觸發 五消特效的時候,我要先找到 哪個是五消型別,哪個是 另一個精靈,再根據另一個精靈的型別 進行mark,

比如 如果是普通的精靈,就直接將所有同類型的mark就行了,

如果是 特效的,就根據開心消消樂的規則 先賦予特效,再mark。

removeSprite函式

// 移除精靈
void GameScene::removeSprite()
{
	// 做一套移除的動作
    isAction = true;
    
	for( int r = 0 ; r < ROWS ; ++r )	{
		for( int c = 0 ; c < COLS ; ++c )	{
			SpriteShape* spr = map[r][c];
			if( !spr )	{
				continue;
			}

			if( spr -> getIsNeedRemove() )	{
				isFillSprite = true;

				if( spr->getDisplayMode() == DISPLAY_MODE_HORIZONTAL)
				{
					this->m_time += 3;
					addTime();
					explodeSpecialH( spr->getPosition() );
				}
				else if (spr->getDisplayMode() == DISPLAY_MODE_VERTICAL)
				{
					this->m_time += 3;
					addTime();
					explodeSpecialV( spr->getPosition() );
				}
				else if (spr->getDisplayMode() == DISPLAY_MODE_BOMB )	{
					this->m_time += 3;
					addTime();
				}
				else if( spr->getDisplayMode() == DISPLAY_MODE_ANY )	{
					this->m_time += 3;
					addTime();
				}
				explodeSprite( spr );
			}
		}
	}
}

其實,沒什麼大改變,因為我沒有新增額外的動畫,所以就是簡簡單單在觸發特效的時候的時間的增加。

恩,現在,兩個特效就有了。

3.新增 特效之間交換 也會消除並觸發相應效果

這個就是特效之間交換也可以消除,比如 縱向消除 與 橫向消除交換,即使它們不是同一種類型,交換後也不會構成消除,也可以觸發各自的特效。

規則是這樣的:

—— 橫向消除 與 橫向消除 、縱向消除 與 縱向消除 、爆炸 與 爆炸 、橫向消除 與 縱向消除

直接交換,然後觸發各自特效就行了

—— 橫向消除 與 爆炸,交換後  橫向消除那個精靈的 上一行 與 下一行 也同時消除(就是三行的消除)

—— 縱向消除 與 爆炸,交換後 縱向消除的那個精靈 上一列 與 下一列 也同時消除(就是三列的消除)

—— 五消 與 五消, 應該是先觸發所有的特效,等下落以後 全爆炸(我圖簡單,直接就全消除了)

五消 與 橫向消除or縱向消除,隨機 將所有同類型精靈 變成橫消或縱消 再消除掉

五消 與 爆炸,將所有同類型精靈 變成 爆炸特效,再消除掉

然後,這個判斷,應該是在交換精靈那裡,就是當我們觸控(滑動)後,執行交換,交換後會判斷有沒有可以消除的精靈,在這裡,我們就應該判斷 交換的兩個精靈是否均不是 特效精靈。

void GameScene::swapSprite()
{
	// 移動中,不允許再次觸控,執行動作設定為true
    isAction = true;
    isTouchEna = false;

	if (!staSprite || !endSprite) {
        return;
    }
    
	Point posOfSrc = staSprite->getPosition();
	Point posOfDest = endSprite->getPosition();

    float time = 0.1;
    
    // 在陣列中交換位置
	map[ staSprite -> getRow() ][staSprite -> getCol() ] = endSprite;
	map[ endSprite -> getRow() ][endSprite -> getCol() ] = staSprite;

    int tmpRow = staSprite->getRow();
    int tmpCol = staSprite->getCol();
    staSprite->setRow(endSprite->getRow());
    staSprite->setCol(endSprite->getCol());
    endSprite->setRow(tmpRow);
    endSprite->setCol(tmpCol);

	

    // 交換的兩個精靈都是特效,或者其中有一個是 五消
	if( (staSprite->getDisplayMode()!=DISPLAY_MODE_NORMAL && endSprite->getDisplayMode()!=DISPLAY_MODE_NORMAL) || 
		(staSprite->getDisplayMode()==DISPLAY_MODE_ANY || endSprite->getDisplayMode()==DISPLAY_MODE_ANY) )	{

		// 如果能夠消除,僅僅進行移動(不會移動回來)
        staSprite->runAction(MoveTo::create(time, posOfDest));
        endSprite->runAction(MoveTo::create(time, posOfSrc));

		// 判斷是哪兩個特效交換
		// 如果兩個特效型別相同,並且不是 五消特效
		if( staSprite->getDisplayMode()==endSprite->getDisplayMode() )	{
			// 如果是兩個五消特效交換
			if( staSprite->getDisplayMode()==DISPLAY_MODE_ANY )	{
				// 全屏消除
				SpriteShape *spr;
				for( int r = 0 ; r < ROWS ; r++ )	{
					for( int c = 0 ; c < COLS ; c++ )	{
						spr = map[r][c];
						markRemove(spr);
					}
				}
			}
			else
			{
				markRemove(staSprite);
				markRemove(endSprite);
			}
			
		}
		// 如果 有一個特效是炸彈
		else if( staSprite->getDisplayMode()==DISPLAY_MODE_BOMB || endSprite->getDisplayMode()==DISPLAY_MODE_BOMB )	{
			// 找到哪個是炸彈
			if( staSprite->getDisplayMode()==DISPLAY_MODE_BOMB )	{
				// 檢視另一個特效
				// 橫向消除特效
				if( endSprite->getDisplayMode()==DISPLAY_MODE_HORIZONTAL )	{

					int dir[3] = {-1,0,1};
					SpriteShape *spr;

					for( int i = 0 ; i < 3 ; i++ )	{
						if( endSprite->getRow()+dir[i] >= 0 && endSprite->getRow()+dir[i] < ROWS )	{
							spr = map[endSprite->getRow()+dir[i]][endSprite->getCol()];
							spr->setDisplayMode(DISPLAY_MODE_HORIZONTAL);
							markRemove(spr);
						}
					}
				}
				// 縱向消除特效
				else if( endSprite->getDisplayMode()==DISPLAY_MODE_VERTICAL )	{

					int dir[3] = {-1,0,1};
					SpriteShape *spr;

					for( int i = 0 ; i < 3 ; i++ )	{
						if( endSprite->getCol()+dir[i] >= 0 && endSprite->getCol()+dir[i] < COLS )	{
							spr = map[endSprite->getRow()][endSprite->getCol()+dir[i]];
							spr->setDisplayMode(DISPLAY_MODE_VERTICAL);
							markRemove(spr);
						}
					}

				}
				// 五消特效
				else if( endSprite->getDisplayMode()==DISPLAY_MODE_ANY )	{

					SpriteShape *spr;
					for( int r = 0 ; r < ROWS ; r++ )	{
						for( int c = 0 ; c < COLS ; c++ )	{
							spr = map[r][c];
							if( spr->getImgIndex() == endSprite->getImgIndex() )	{
								spr->setDisplayMode(DISPLAY_MODE_BOMB);
								markRemove(spr);
							}
						}
					}

				}

			}
			else
			{
				// 檢視另一個特效
				// 橫向消除特效
				if( staSprite->getDisplayMode()==DISPLAY_MODE_HORIZONTAL )	{

					int dir[3] = {-1,0,1};
					SpriteShape *spr;

					for( int i = 0 ; i < 3 ; i++ )	{
						if( staSprite->getRow()+dir[i] >= 0 && staSprite->getRow()+dir[i] < ROWS )	{
							spr = map[staSprite->getRow()+dir[i]][staSprite->getCol()];
							spr->setDisplayMode(DISPLAY_MODE_HORIZONTAL);
							markRemove(spr);
						}
					}

				}
				// 縱向消除特效
				else if( staSprite->getDisplayMode()==DISPLAY_MODE_VERTICAL )	{

					int dir[3] = {-1,0,1};
					SpriteShape *spr;

					for( int i = 0 ; i < 3 ; i++ )	{
						if( staSprite->getCol()+dir[i] >= 0 && staSprite->getCol()+dir[i] < COLS )	{
							spr = map[staSprite->getRow()][staSprite->getCol()+dir[i]];
							spr->setDisplayMode(DISPLAY_MODE_VERTICAL);
							markRemove(spr);
						}
					}

				}
				// 五消特效
				else if( staSprite->getDisplayMode()==DISPLAY_MODE_ANY )	{

					SpriteShape *spr;
					for( int r = 0 ; r < ROWS ; r++ )	{
						for( int c = 0 ; c < COLS ; c++ )	{
							spr = map[r][c];
							if( spr->getImgIndex() == staSprite->getImgIndex() )	{
								spr->setDisplayMode(DISPLAY_MODE_BOMB);
								markRemove(spr);
							}
						}
					}

				}
			}

		}
		// 如果 有一個特效是 五消
		else if( staSprite->getDisplayMode()==DISPLAY_MODE_ANY || endSprite->getDisplayMode()==DISPLAY_MODE_ANY )	{

			if( staSprite->getDisplayMode() == DISPLAY_MODE_ANY )	{

				if( endSprite->getDisplayMode() == DISPLAY_MODE_NORMAL )	{
					markRemove(staSprite);
					markRemove(endSprite);
				}
				// 另一個是 豎消 或者 橫消
				else
				{

					SpriteShape *spr;
					for( int r = 0 ; r < ROWS ; r++ )	{
						for( int c = 0 ; c < COLS ; c++ )	{
							spr = map[r][c];
							if( spr->getImgIndex() == endSprite->getImgIndex() )	{
								// 隨機 橫消或者豎消
								float _rand = myRand_0_1();
								if( _rand < 0.5 )	{
									spr->setDisplayMode(DISPLAY_MODE_HORIZONTAL);
								}
								else
								{
									spr->setDisplayMode(DISPLAY_MODE_VERTICAL);
								}

								markRemove(spr);
							}
						}
					}
				}
			}
			else
			{
				if( staSprite->getDisplayMode() == DISPLAY_MODE_NORMAL )	{
					markRemove(staSprite);
					markRemove(endSprite);
				}
				// 另一個是 豎消 或者 橫消
				else 
				{
					SpriteShape *spr;
					for( int r = 0 ; r < ROWS ; r++ )	{
						for( int c = 0 ; c < COLS ; c++ )	{
							spr = map[r][c];
							if( spr->getImgIndex() == staSprite->getImgIndex() )	{
								// 隨機 橫消或者豎消
								float _rand = myRand_0_1();
								if( _rand < 0.5 )	{
									spr->setDisplayMode(DISPLAY_MODE_HORIZONTAL);
								}
								else
								{
									spr->setDisplayMode(DISPLAY_MODE_VERTICAL);
								}

								markRemove(spr);
							}
						}
					}
				}
			}
		}
		// 剩下的就是 橫消+豎消組合
		else
		{
			markRemove(staSprite);
			markRemove(endSprite);
		}

		removeSprite();

        return;
	}

    // 檢查是否能消除
	std::list<SpriteShape *> colChainListOfFirst;
    getColChain(staSprite, colChainListOfFirst);
    
    std::list<SpriteShape *> rowChainListOfFirst;
    getRowChain(staSprite, rowChainListOfFirst);
    
    std::list<SpriteShape *> colChainListOfSecond;
    getColChain(endSprite, colChainListOfSecond);
    
    std::list<SpriteShape *> rowChainListOfSecond;
    getRowChain(endSprite, rowChainListOfSecond);
    
    if (colChainListOfFirst.size() >= 3
        || rowChainListOfFirst.size() >= 3
        || colChainListOfSecond.size() >= 3
        || rowChainListOfSecond.size() >= 3 
		|| staSprite->getDisplayMode()==DISPLAY_MODE_ANY 
		|| endSprite->getDisplayMode()==DISPLAY_MODE_ANY
		) {
        // 如果能夠消除,僅僅進行移動(不會移動回來)
        staSprite->runAction(MoveTo::create(time, posOfDest));
        endSprite->runAction(MoveTo::create(time, posOfSrc));
        return;
    }
    
    // 不能消除,則移動過去還要返回
	map[ staSprite -> getRow()][staSprite -> getCol() ] = endSprite;
	map[ endSprite -> getRow()][endSprite -> getCol() ] = staSprite;

    tmpRow = staSprite->getRow();
    tmpCol = staSprite->getCol();
    staSprite->setRow(endSprite->getRow());
    staSprite->setCol(endSprite->getCol());
    endSprite->setRow(tmpRow);
    endSprite->setCol(tmpCol);
    
    staSprite->runAction(Sequence::create(
                                      MoveTo::create(time, posOfDest),
                                      MoveTo::create(time, posOfSrc),
                                      NULL));
    endSprite->runAction(Sequence::create(
                                      MoveTo::create(time, posOfSrc),
                                      MoveTo::create(time, posOfDest),
                                      NULL));
}



這裡的判斷順序是這樣的:

——是否同類型

————其中一個為 五消(肯定另一個也是五消了)

——其中一個為 炸彈

————另一個為 橫消

————另一個為 縱消

————另一個為 五消

——其中一個為 五消

————另一個為 普通精靈

————另一個為 橫消 或 縱消

——剩下 就是 橫消+縱消 的組合了

這個 if-else 關係,不知道能不能看懂= =。

4.觸控式螢幕蔽 and 交換處 優先判斷

這裡有些小問題,我們在判斷它有哪些精靈爆炸的時候,有先後順序。

比如,上面 第一張圖 T字形,產生五消的形狀。

如果我們,直接兩個for迴圈,從0~ROWS ,0~COLS,來判斷形狀生成特效的話,的確可以產生五消特效,但是,凸出來的那部分(應該消除的),沒有被消除,因為按我們的判斷邏輯,是從頭開始判斷,看下面圖:(圖好醜啊= =。)


我們從 1號開始判斷,橫向5個,縱向1個(假設),所以,要產生 五消特效精靈,

staSprite或者endSprite肯定是3號那個,所以,3變成五消特效,1,2,4,5會消除,6,7反而會留下。

但,正確的應該是,3變成五消特效,1,2,4,5,6,7 消除。

所以,應該就先判斷交換處的精靈關係,再從頭開始遍歷。

if( staSprite!=NULL && !staSprite->getIsNeedRemove() && !staSprite->getIgnoreCheck() )	{
    removeAndPro(staSprite);
}
if( endSprite!=NULL && !endSprite->getIsNeedRemove() && !endSprite->getIgnoreCheck() )	{
    removeAndPro(endSprite);
}

最後,之前 遊戲結束,還可以進行交換,我這裡就加上一個觸控式螢幕蔽層把。

非常簡單,就是遊戲結束的時候,加一個layer,這個layer將 觸控事件吞掉。

//*********SwallowLayer.h

#ifndef __SWALLOWLAYER_H__
#define __SWALLOWLAYER_H__

#include "cocos2d.h"

USING_NS_CC;

class SwallowLayer : public Layer
{
public:
	/***** 初始化函式 *****/
	virtual bool init();  
	CREATE_FUNC(SwallowLayer);

};

#endif


//******** SwallowLayer.cpp

#include "SwallowLayer.h"

bool SwallowLayer::init( )	
{
	if( !Layer::init() )	{
		return false;
	}

    // 新增監聽器
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan= [this](Touch* t,Event* e){
		CCLOG("touch swallow layer");
		return true;
	};
	listener->setSwallowTouches(true);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);


	return true;
}


好了,大體已經完成了。

雖然,還有一些瑕疵,唉。。。

馬上就去北京找實習了,祝自己好運吧~= =~

本篇 完整程式碼+資源:百度雲盤

本篇 最終 APK:百度雲盤

***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************