首页 技术 正文
技术 2022年11月11日
0 收藏 456 点赞 3,599 浏览 7045 个字

背景

在上一篇博客中,我们提到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);
//通过地图块坐标返回地图块类型
enumTileTypeTileMapPosToTileType(CCPoint HeroPos,float fMapMove);
//地图块坐标转换为地图层坐标
CCPointTileMapPosToTileMapLayerPos(CCPoint TileMapPos);
//地图层坐标转换为世界坐标
CCPointTileMapLayerPosToWorldPos(CCPoint TileMapLayerPos,float m_fMapMove);
//地图层坐标转换为地图块坐标
CCPointTileMapLayerPosToTileMapPos(CCPoint TileMapLayerPos);
//返回地图偏移量
floatGetMapMove();
virtual void OnCallPerFrame(float dt);
protected:
virtual bool Init();void onExit();//Mario碰撞
voidMarioMove(float fT);
//顶砖块
voidHitBlock(CCPoint TileMapLayerPos);
//删除砖块
voidDeleteBlock();//消息处理
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地图了。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,075
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,551
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,399
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,176
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,811
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,893