cocos2d-x 3.4 之 三消类游戏——万圣大作战(附加篇)

cocos2d-x 3.4 之 三消类游戏——万圣大作战(附加篇),第1张

概述***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 三消游戏——万圣大作战,应该是我最早的教程的教程之一了(总共也没几个o(╯□╰)o) 之前就简单实现了 消除,四消这些; 发布以来,很多人问我 爆炸 肿么办? 五

***************************************转载请注明出处: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,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_ANY);			}		}   		// 只消除 横向 精灵 ,产生五消精灵		else		{			removeListSpr(rowChainList,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,isChangePro);			removeListSpr(rowChainList,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_ANY);			}		}		else		{			// 只消除 纵向 精灵 ,产生五消精灵			removeListSpr(colChainList,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,disPLAY_MODE_BOMB,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_BOMB);			}		}		else		{			// 消除 横向精灵,产生四消精灵			removeListSpr(rowChainList,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,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_BOMB);			}		}		else		{			// 消除 纵向精灵,产生四消精灵			removeListSpr(colChainList,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,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_BOMB);			}		}		else		{			// 消除横向精灵			removeListSpr(rowChainList,isChangePro);		}		return;	}	if( colChainList.size() >= 3 )	{		if( rowChainList.size() >= 3 )	{			removeListSpr(colChainList,isChangePro);			// 自由掉落产生			if( isChangePro == false )	{				spr->setIgnoreCheck(true);				spr->setIsNeedRemove(false);				spr->setdisplayMode(disPLAY_MODE_BOMB);			}		}		else		{			// 消除纵向精灵			removeListSpr(colChainList,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);            }        }    }	// 消除的是 炸d特效 的精灵	else if( spr->getdisplayMode() == disPLAY_MODE_BOMB )	{		int dir[12][2] = {0,-2,2,-1,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);			}					}		// 如果 有一个特效是炸d		else if( staSprite->getdisplayMode()==disPLAY_MODE_BOMB || endSprite->getdisplayMode()==disPLAY_MODE_BOMB )	{			// 找到哪个是炸d			if( staSprite->getdisplayMode()==disPLAY_MODE_BOMB )	{				// 查看另一个特效				// 横向消除特效				if( endSprite->getdisplayMode()==disPLAY_MODE_HORIZONTAL )	{					int dir[3] = {-1,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,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,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,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,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,NulL));}



这里的判断顺序是这样的:

——是否同类型

————其中一个为 五消(肯定另一个也是五消了)

——其中一个为 炸d

————另一个为 横消

————另一个为 纵消

————另一个为 五消

——其中一个为 五消

————另一个为 普通精灵

————另一个为 横消 或 纵消

——剩下 就是 横消+纵消 的组合了

这个 if-else 关系,不知道能不能看懂= =。




4.触摸屏蔽 and 交换处 优先判断

这里有些小问题,我们在判断它有哪些精灵爆炸的时候,有先后顺序。

比如,上面 第一张图 T字形,产生五消的形状。

如果我们,直接两个for循环,从0~ROWS ,0~ColS,来判断形状生成特效的话,的确可以产生五消特效,但是,凸出来的那部分(应该消除的),没有被消除,因为按我们的判断逻辑,是从头开始判断,看下面图:(图好丑啊= =。)


我们从 1号开始判断,横向5个,纵向1个(假设),所以,要产生 五消特效精灵,

staSprite或者endSprite肯定是3号那个,所以,3变成五消特效,1,4,5会消除,6,7反而会留下。

但,正确的应该是,3变成五消特效,1,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:百度云盘




********************************************

总结

以上是内存溢出为你收集整理的cocos2d-x 3.4 之 三消类游戏——万圣大作战(附加篇)全部内容,希望文章能够帮你解决cocos2d-x 3.4 之 三消类游戏——万圣大作战(附加篇)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1072560.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存