zoukankan      html  css  js  c++  java
  • cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap

    背景

    在上一篇博客中,我们提到CMGameScene,但是CMGameScene只是个框架,实际担任游戏逻辑的是CMGameMap类,这个博文就来了解下CMGameMap


    头文件

    class CMGameMap : public cocos2d::CCTMXTiledMap ,public CMReceiver
    {
    protected:
    	enum 
    	{
    		enTagMario = 998,				//通过这个Tag查找Mario
    	};
    protected:
    	CCArray	*m_pArrayItems;				//金币数组
    	CCArray *m_pArrayMonsters;			//怪物数组
    	CCArray *m_pArrayBlocks;				//砖块数组
    
    	float m_fMapMove;					//地图偏移量
    	float m_fDropSpeedPlus;				//掉落速度
    	float m_fJumpSpeed;					//跳跃速度
    
    	bool m_bIsLeftKeyDown;				//左键是否按下
    	bool m_bIsRightKeyDown;				//右键是否按下
    	bool m_bIsJumpKeyDown;				//跳跃键是否按下
    	bool m_bIsHeroDead;					//是否死亡
    public:
    	static CMGameMap* CreateGameMap(const char* pFileName);
    
    	// 返回地图指定位置上的图块
    	CCSprite*	TileMapLayerPosToTileSprite(CCPoint TileMapLayerPos);			
    	//通过地图块坐标返回地图块类型
    	enumTileType	TileMapPosToTileType(CCPoint HeroPos,float fMapMove);					
    	//地图块坐标转换为地图层坐标
    	CCPoint		TileMapPosToTileMapLayerPos(CCPoint TileMapPos);							
    	//地图层坐标转换为世界坐标
    	CCPoint		TileMapLayerPosToWorldPos(CCPoint TileMapLayerPos,float m_fMapMove);
    	//地图层坐标转换为地图块坐标
    	CCPoint		TileMapLayerPosToTileMapPos(CCPoint TileMapLayerPos);
    	//返回地图偏移量
    	float		GetMapMove();
    	virtual void OnCallPerFrame(float dt);
    protected:
    	virtual bool Init();
    	
    	void		 onExit();
    
    	//Mario碰撞
    	void	MarioMove(float fT);
    	//顶砖块
    	void	HitBlock(CCPoint TileMapLayerPos);
    	//删除砖块
    	void	DeleteBlock();
    
    	//消息处理
    protected:
    	virtual void OnMsgReceive( int enMsg,void* pData,int nSize );
    	
    	void OnSubMsgItemRemove(void *pData ,int nSize);	//[道具移除]消息处理
    
    	void OnSubMsgMarioLevelUp();						//[马里奥长大]消息处理
    
    	void OnSubMsgMonsterDisappear(void *pData,int nSize);//[怪物消失]消息处理
    
    	void OnSubMsgStamp(void *pData,int nSize);			//[被马里奥踩踏]消息处理
    	
    	void OnSubMsgBlockBoxHitted(void *pData,int nSize);	//	[砖块被顶]消息处理
    
    	void OnSubMsgMarioBeHurt();							//马里奥被伤害的消息处理
    };

    从头文件上CMGameMap是从CCTMXTileMap派生,CCTMXTileMap是cocos2dx中的一个瓦片地图类,会有别的博文对这个类进行详细解释,目前我们知道它是CCNode的子类即可。

    这个类作为容纳游戏逻辑的类,里面有很多的成员:

    m_pArrayItems:  道具,是指在地图上显示的金币等道具

    m_pArrayMonsters:怪物

    m_pArrayBlocks:砖头


    m_fMapMove: 在这个游戏里,地图比窗口大,窗口只能显示地图的一部分,这个值表示窗口原点和地图原点的偏移

    m_fDropSpeedPlus: 马里奥掉落速度

    m_fJumpSpeed:跳跃速度


    m_bIsLeftKeyDown:左键是否按下

    m_bisRightKeyDown:右键是否按下

    m_bIsJumpKeyDown:跳跃是否按下

    以上三个标记,用于连续操作

    m_bIsHeroDead:   马里奥是否死亡


    CreateGameMap:创建地图

    TileMapLayerPosToTileSprite(CCPoint TileMapLayerPos):根据位置获得精灵

    TileMapPosToTileType(CCPoint, float fMapMove):根据位置获得精灵类型

    TileMapPosToTileMapLayerPos(CCPoint tileMapPos):根据地图坐标,获取砖块坐标

    TileMapLayerPosToWorldPos:通过砖块坐标转化成世界坐标,也就是cocos2d的坐标

    TileMapLayerPosToTileMapPos:将图层坐标转化成地图块坐标


    GetMapMove:获取地图偏移

    OnCallPerFrame:被CMGameScene调用的函数,进行逻辑处理,每一帧刷新都会调用该函数

    Init:初始化

    MarioMove:马里奥移动时,判断游戏逻辑

    HitBlock:撞砖块

    DeleteBlock:删除砖块


    OnMsgReceive:接收到地图中的精灵发过来的消息

    OnSubMsg系列函数:对响应的精灵发过来的消息进行处理


    CreateGameMap

    该函数是本类第一个被调用的函数,详细内容如下:

    CMGameMap* CMGameMap::CreateGameMap(const char* pFileName)
    {
    	do 
    	{
    		CMGameMap* pPlayer = new CMGameMap;
    		if (pPlayer && pPlayer->initWithTMXFile(pFileName))
    		{
    			pPlayer->Init();
    			pPlayer->autorelease();
    			return pPlayer;
    		}
    		delete pPlayer;
    	} while (false);
    	CCLog("Fun CMGameMap::CreateGameMap Error!");
    	return NULL;
    }
    这个函数调用了initWithTMXFile函数,这个函数是初始化瓦片地图的函数,在别的博客里详细解释


    Init

    init函数负责初始化地图中所有的精灵,各就各位,准备游戏

    bool CMGameMap::Init()
    {
    	do 
    	{
    		//初始化成员变量
    		m_fMapMove = 0;
    		m_fDropSpeedPlus = 0;
    		m_fJumpSpeed = 0;
    		m_bIsLeftKeyDown = false;
    		m_bIsRightKeyDown = false;
    		m_bIsJumpKeyDown = false;
    		m_bIsHeroDead = false;
    
    		//初始化游戏对象数组
    		m_pArrayItems = CCArray::create();
    		m_pArrayItems->retain();
    		m_pArrayMonsters = CCArray::create();
    		m_pArrayMonsters->retain();
    		m_pArrayBlocks = CCArray::create();
    		m_pArrayBlocks->retain();
    
    		//初始化Mario
    		CMMario* pMario = CMMario::CreateHero(this);
    		CC_BREAK_IF(pMario==NULL);
    		pMario->setPosition(TileMapPosToTileMapLayerPos(ccp(2,11)));
    		addChild(pMario,enZOrderFront,enTagMario);
    		//pMario->SetStatus(enMarioStatusBig);
    
    		//隐藏原落坑判断层
    		CCTMXLayer* pTrapLayer = layerNamed("trap");
    		CC_BREAK_IF(pTrapLayer==NULL);
    		pTrapLayer->setVisible(false);
    
    		//初始化显示金币
    		CCTMXLayer* pCoinLayer = layerNamed("coin");
    		CC_BREAK_IF(pCoinLayer==NULL);
    		pCoinLayer->setVisible(false);
    		//获得地图的瓦片数量
    		int nMapHorizontalTileNum = pCoinLayer->boundingBox().size.width/getTileSize().width;
    		int nMapVerticalTileNum = pCoinLayer->boundingBox().size.height/getTileSize().height;
    		//遍历每片瓦片,寻找金币,建立并加入金币集合
    		for (int i = 0;i<nMapHorizontalTileNum;i++)
    		{
    			for (int j = 0;j<nMapVerticalTileNum;j++)
    			{
    				if (TileMapPosToTileType(ccp(i,j),m_fMapMove)==enTileTypeCoin)
    				{
    					//将瓦片地图坐标转换为瓦片地图层坐标
    					CCPoint CoinTileMapLayerPos = TileMapPosToTileMapLayerPos(ccp(i,j));
    					CMItemCoin* pCoin = CMItemCoin::CreateItemIcon(CoinTileMapLayerPos,getTileSize(),pMario,this);
    					if (pCoin==NULL)
    					{
    						CCLog("Coin init Error!");
    					}
    					pCoin->setPosition(CoinTileMapLayerPos);
    					pCoin->setAnchorPoint(ccp(0,0));
    					m_pArrayItems->addObject(pCoin);
    					addChild(pCoin);
    				}
    			}
    		}
    
    		//初始化怪物显示
    		CCTMXObjectGroup* pObjectLayer = objectGroupNamed("objects");
    		CC_BREAK_IF(pObjectLayer==NULL);
    		CCArray *ObjectArray = pObjectLayer->getObjects();
    		CCDictionary *pDic = NULL;
    		for (unsigned int i = 0; i < ObjectArray->count(); i++)
    		{
    			pDic = (CCDictionary *)ObjectArray->objectAtIndex(i);
    			int PosX = ((CCString*)pDic->objectForKey("x"))->intValue();
    			int PosY = ((CCString*)pDic->objectForKey("y"))->intValue();
    			PosY -= this->getTileSize().height;
    			CCPoint TileXY = ccp(PosX, PosY);
    
    			CCString *strName = (CCString*)pDic->objectForKey("name");
    			CCString *strType = (CCString*)pDic->objectForKey("type");
    
    			// 进行怪物的初始化,先根据名字来判断是不是enemy,再细分enemy类型		
    			if (strName->m_sString == "enemy")
    			{
    				if (strType->m_sString == "mushroom")
    				{
    					CMMonsterMushrooms *pMonster = CMMonsterMushrooms::CreateMonsterMushrooms(TileXY,pMario,this,this);
    					if (pMonster==NULL)
    					{
    						CCLog("pMonster==NULL!");
    					}
    					pMonster->setPosition(ccp(TileXY.x,TileXY.y));
    					pMonster->setAnchorPoint(ccp(0,0));
    					m_pArrayMonsters->addObject(pMonster);
    					addChild(pMonster,enZOrderFront);
    				}
    				if (strType->m_sString == "tortoise")
    				{
    					CMMonsterTortoise *pMonster = CMMonsterTortoise::CreateMonsterTortoise(TileXY,pMario,this,this);
    					if (pMonster==NULL)
    					{
    						CCLog("pMonster==NULL!");
    					}
    					pMonster->setPosition(ccp(TileXY.x,TileXY.y));
    					pMonster->setAnchorPoint(ccp(0,0));
    					m_pArrayMonsters->addObject(pMonster);
    					addChild(pMonster,enZOrderFront);
    				}
    				if (strType->m_sString == "flower")
    				{
    					CMMonsterFlower *pMonster = CMMonsterFlower::CreateMonsterFlower(TileXY,pMario,this,this);
    					if (pMonster==NULL)
    					{
    						CCLog("pMonster==NULL!");
    					}
    					pMonster->setPosition(ccp(TileXY.x,TileXY.y));
    					pMonster->setAnchorPoint(ccp(0,0));
    					m_pArrayMonsters->addObject(pMonster);
    					addChild(pMonster,enZOrderFront);
    				}
    			}
    		}
    
    		//初始化砖块显示
    		CCTMXLayer* pBlockLayer = layerNamed("block");
    		CC_BREAK_IF(pBlockLayer==NULL);
    		pBlockLayer->setVisible(false);
    		//获得地图的瓦片数量
    		// 		int nMapHorizontalTileNum = pCoinLayer->boundingBox().size.width/getTileSize().width;
    		// 		int nMapVerticalTileNum = pCoinLayer->boundingBox().size.height/getTileSize().height;
    		//遍历每片瓦片,寻找瓦片,建立并加入瓦片集合
    		for (int i = 0;i<nMapHorizontalTileNum;i++)
    		{
    			for (int j = 0;j<nMapVerticalTileNum;j++)
    			{
    				if (TileMapPosToTileType(ccp(i,j),m_fMapMove)==enTileTypeBlock)
    				{
    					//解析得到当前砖块的属性
    					int GID = pBlockLayer->tileGIDAt(ccp(i,j));
    					CCDictionary *pDic = propertiesForGID(GID);
    					CC_BREAK_IF(pDic==NULL);
    					CCString *strBlockType = (CCString*)pDic->objectForKey("blockType");
    					if (strBlockType==NULL)
    					{
    						continue;
    					}
    					int nBlockType = strBlockType->intValue();
    
    					//将瓦片地图坐标转换为瓦片地图层坐标
    					CCPoint BlockTileMapLayerPos = TileMapPosToTileMapLayerPos(ccp(i,j));
    					CMItemBlock* pBlock = CMItemBlock::CreateItemBlock(BlockTileMapLayerPos,getTileSize(),pMario,this,(enumBlockType)nBlockType);
    					if (pBlock==NULL)
    					{
    						CCLog("Block init Error!");
    					}
    					pBlock->setPosition(BlockTileMapLayerPos);
    					pBlock->setAnchorPoint(ccp(0,0));
    					m_pArrayBlocks->addObject(pBlock);
    					addChild(pBlock);
    				}
    			}
    		}
    
    		return true;
    	} while (false);
    	CCLog("Fun CMGameMap::Init Error!");
    	return false;
    }

    这里很多精灵是从TMX地图中获得的,因此如果需要进一步学习马里奥的话,需要先了解TMX地图了。


  • 相关阅读:
    php怎么实现多态?
    php怎么识别真实ip
    php析构函数什么时候调用?
    php解析xml的几种方式
    thinkPHP5框架路由常用知识点汇总
    用Python打造了一个渗透测试暴力探测器
    修复wecenter移动版description首页描述一样问题
    寒假小软件开发记录02--布局
    寒假小软件开发记录01--确定方向和素材准备
    大二上学期个人总结
  • 原文地址:https://www.cnblogs.com/new0801/p/6177217.html
Copyright © 2011-2022 走看看