cocos2d-x游戏开发系列教程-超级玛丽09-怪物激活与移动

在游戏中,很多怪物本身是会移动的,这里主要有蘑菇怪,乌龟等。

说起怪物的移动,首先在游戏里先要考虑怪物的抽象和设计。


在CMMonster.h中,有个类CMMonsterBasic,这个类抽象了所有的怪物,具体的怪物都是它的派生类,比如CMMonsterMushrooms蘑菇怪。


CMMonsterBasic继承自CCNode和CMSender,所以怪物都是渲染对象,并且有消息发送功能。

怪物基本类的接口:

virtual bool init(CCPoint ptMonsterPos,CMMario *pMario,CMGameMap *pGameMap,CMReceiver *pReceiver); 初始化

virtual bool OnCollisionMario() = 0;  与马里奥相撞处理

virtual void Dead(enMonsterDeadType DeadType); 怪物死亡

virtual bool OnCallPerFrame(float fT);  帧刷新定时调用

void MonsterTurn(); 怪物转向,比如蘑菇怪遇到阻挡它的墙时,它会转向


怪物类的基本数据

CMMario                *m_pMario;   马里奥对象

CMGameMap            *m_pGameMap; 地图对象

enMoveDirection         m_MoveDirection;  移动方向

bool                 m_bIsActivation;              是否激活

float                 m_fDropSpeedPlus;     掉落加速度

bool                 m_bIsTouched;   是否相撞


怪物的创建:

当游戏开始时,根据tmx地图中的标记,创建怪物对象并放置到响应位置,具体代码在CMGameMap的init函数中

创建完怪物之后,将其加入到数组中,这些怪物刚刚创建时候,都是不激活的,也就是不会动的


怪物的激活和移动:

触发怪物的激活的原理在于判断怪物是不是已经进入视图,如果没有进入视图,那么怪物不需要动。但是判断是否进入视图还是很麻烦的,所以在马里奥程序里,是用马里奥和怪物的距离,来触发怪物的激活的。

怪物的激活和移动都是在virtual bool OnCallPerFrame(float fT); 函数中,这个函数是CMGameMap的帧更新函数调用过来的,也就是说每次帧更新,每个怪物都会响应这个函数。在这个函数里,负责激活和移动,以及判断怪物和马里奥的碰撞。

下面我们以蘑菇怪的帧更新函数来学习怪物帧更新处理。

bool CMMonsterMushrooms::OnCallPerFrame( float fT )
{
	do 
	{
		//是否激活
		if (m_bIsActivation==true)
		{
			//移动与碰撞
			if (m_MoveDirection == enMoveLeft)
			{
				//用怪物左方的2个瓦片来判断移动碰撞
				CCSprite* pTileSpriteLeftTop = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX(),getPositionY()+getContentSize().height));
				CCSprite* pTileSpriteLeftMid = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX(),getPositionY()+getContentSize().height/2));
				if (pTileSpriteLeftTop!=NULL || pTileSpriteLeftMid!=NULL)
				{
					m_MoveDirection = enMoveRight;
				}
				else
				{
					setPositionX(getPositionX()-1);
				}
			}
			else if(m_MoveDirection == enMoveRight)
			{
				//用怪物右方的2个瓦片来判断移动碰撞
				CCSprite* pTileSpriteRightTop = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX()+getContentSize().width,getPositionY()+getContentSize().height));
				CCSprite* pTileSpriteRightMid = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX()+getContentSize().width,getPositionY()+getContentSize().height/2));
				if (pTileSpriteRightTop!=NULL || pTileSpriteRightMid!=NULL)
				{
					m_MoveDirection = enMoveLeft;
				}
				else
				{
					setPositionX(getPositionX()+1);
				}
			}

			//用怪物下方的三个瓦片来判断掉落碰撞
			CCSprite* pTileSpriteBottomMid = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX()+boundingBox().size.width/2,getPositionY()));
			CCSprite* pTileSpriteBottomLeft = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX()+COLLISION_POS_ADJUSTMENT,getPositionY()));
			CCSprite* pTileSpriteBottomRight = m_pGameMap->TileMapLayerPosToTileSprite(ccp(getPositionX()+boundingBox().size.width-COLLISION_POS_ADJUSTMENT,getPositionY()));
			if (pTileSpriteBottomLeft!=NULL || pTileSpriteBottomMid!=NULL || pTileSpriteBottomRight!=NULL)
			{
				//掉落速度归零
				m_fDropSpeedPlus = 0;
			}
			else
			{
				setPositionY(getPositionY()-m_fDropSpeedPlus);
				//掉落加速度
				m_fDropSpeedPlus += DROP_SPEED_PLUS;
			}
		}

		

		return (CMMonsterBasic::OnCallPerFrame(fT)||OnCollisionMario());
	} while (false);
	
	CCLog("fun CMMonsterMushrooms::OnCallPerFrame Error!");

	return false;
}

首先判断是否激活了,如果激活了那么则判断它的移动,它不需要按键驱动,按照时间移动它即可,遇到障碍物则返回。如果蘑菇怪在天上,则自然降落。


最后调用基类的定时刷新函数和马里奥的冲突函数。基类的定时刷新函数做什么呢

bool CMMonsterBasic::OnCallPerFrame(float fT)
{
	do 
	{
		//判断当怪物离开地图则发消息删除自己
		if (getPositionX()<0 || getPositionY()<0)
		{
			TCmd_Remove_Monster* pData = new TCmd_Remove_Monster;
			pData->pMonster = this;
			SendMsg(enMsgMonsterDisappear,pData,sizeof(pData));
			return true;//需要删除自己
		}

		CC_BREAK_IF(m_pMario==NULL);

		//判断马里奥与当前怪物的距离,用以激活。
		if (abs(m_pMario->getPositionX() - getPositionX())<MONSTER_ACTIVE_DISTANCE)
		{
			m_bIsActivation = true;
		}

		return false;//不需要删除自己
	} while (false);
	CCLog("fun CMMonsterBasic::OnCallPerFrame Error!");
	return false;
}

基类的函数主要要做的事情是:

1)如果怪物离开地图,则自杀。自杀是通过发送消息给地图类,让地图类杀掉本对象

2)如果怪物与马里奥的距离小于某个值,则激活,激活的意思就是这个怪物开始运动了



原文地址:https://www.cnblogs.com/new0801/p/6177206.html