魔塔中会有地图切换的需求。我们首先在TileMap中绘制传送点。打开Tiled编辑器,选中object层,选择工具栏中的“插入对象”按钮,在地图(6,1)处创建一个对象,编辑其属性如下所示。其中,“类型”项用来区分对象是否为传送点,heroTileCoordX和heroTileCoordY定义了勇士在目标地图中出现的坐标,targetMap定义了目标地图的层数。down_floor.png是用来显示的图片纹理,我们首先把down_floor.png和up_floor.png复制到我们的项目中。
下面我们来创建Teleport对象,用于记录上述配置信息,具体头文件如下:
#ifndef __TELEPORT_H__ #define __TELEPORT_H__ #include "MTGame.h" using namespace cocos2d; class Teleport:public CCObject { public: Teleport(CCDictionary *dict,int x,int y); ~Teleport(); //传送点所在位置 CCPoint tileCoord; //传送到目标后,勇士所在坐标 CCPoint heroTileCoord; //目标地图的层数 int targetMap; //唯一的ID int index; //图片纹理的文件路径 CCString *imagePath; CCSprite *teleportSprite; }; #endif
#include "Teleport.h" Teleport::Teleport(CCDictionary *dict,int x,int y) { CCPoint position=ccp(x,y); //传送点所在的TileMap位置 tileCoord=sGlobal->gameMap->tileCoordForPosition(position); //得出勇士目标层的起始位置 std::string key="heroTileCoordX"; int x1=((CCString*)dict->objectForKey(key))->intValue(); key="heroTileCoordY"; int y1=((CCString*)dict->objectForKey(key))->intValue(); heroTileCoord=ccp(x1,y1); //取得目标地图的层数 key="targetMap"; targetMap=((CCString*)dict->objectForKey(key))->intValue(); //取得image项 key="image"; imagePath=(CCString*)dict->objectForKey(key); //创建用于显示Teleport的精灵 teleportSprite=CCSprite::create(imagePath->m_sString.c_str()); teleportSprite->setAnchorPoint(CCPointZero); teleportSprite->setPosition(position); sGlobal->gameLayer->addChild(teleportSprite,kZTeleport); } //析构函数 Teleport::~Teleport() { CC_SAFE_DELETE(imagePath); CC_SAFE_DELETE(teleportSprite); }
在GameMap的initObject方法中,遍历object层的所有对象时,判断对象类型如果是teleport,则新创建一个Teleport对象,并存放到teleport中。
//如果是传送门 else if(type->m_sString=="teleport") { Teleport *teleport=new Teleport(dict,x,y); teleportDict->setObject(teleport,index); }
//在Teleport字典中查询 Teleport* teleport=(Teleport*)sGlobal->gameMap->teleportDict->objectForKey(index); if(NULL!=teleport) { doTeleport(teleport); return kTeleport; }
//切换地图 void GameScene::switchMap() { //创建一个遮罩层,用于地图切换时显示淡入淡出的效果 CCLayerColor *fadelayer=CCLayerColor::create(ccc4(0,0,0,0)); fadelayer->setAnchorPoint(CCPointZero); fadelayer->setPosition(CCPointZero); this->addChild(fadelayer,kFadeLayer,kFadeLayer); //执行淡入动画,结束时调用resetGameLayer方法 CCAction *action=CCSequence::create( CCFadeIn::create(0.5f), CCCallFunc::create(this, callfunc_selector(GameScene::resetGameLayer)), NULL); fadelayer->runAction(action); }
resetGameLayer方法如下。开始时先删除当前的gameLayer对象,再用create方法创建新的gameLayer,最后让遮罩层执行CCFadeOut操作,并且注册了一个回调函数,用于移除遮罩层:
//切换游戏地图 void GameScene::resetGameLayer() { //删除老的GameLayer this->removeChildByTag(kGameLayer,true); //创建新的GameLayer GameLayer *gameLayer=GameLayer::create(); this->addChild(gameLayer,kGameLayer,kGameLayer); //执行淡出动画,结束后,调用removeFadeLayer方法 CCAction *action=CCSequence::create( CCFadeOut::create(0.5f), CCCallFunc::create(this, callfunc_selector(GameScene::removeFadeLayer)), NULL); this->getChildByTag(kFadeLayer)->runAction(action); }
//删除遮罩层 void GameScene::removeFadeLayer() { this->removeChildByTag(kFadeLayer,true); }
//目标地图的层数 int currentLevel; //勇士出现的位置 CCPoint heroSpawnTileCoord;
//解析TMX地图 char temp[20]; sprintf(temp,"%d.tmx",sGlobal->currentLevel); map=GameMap::gameMapWithTMXFile(temp); addChild(map); //调用Hero类的静态方法创建实例 hero=Hero::heroWithinLayer(); //设置Hero的起始位置 hero->setPosition(map->positionForTileCoord(sGlobal->heroSpawnTileCoord)); //将Hero加入GameLayer addChild(hero);
//新游戏,当前地图层数为0 sGlobal->currentLevel=0; //勇士出生的位置 sGlobal->heroSpawnTileCoord=ccp(1,11);
//处理传送门 void Hero::doTeleport(Teleport *teleport) { //从传送点的属性中设置目标地图的层数 sGlobal->currentLevel=teleport->targetMap; //获取勇士在新地图中的起始位置 sGlobal->heroSpawnTileCoord=teleport->heroTileCoord; //开始切换地图 sGlobal->gameScene->switchMap(); }
将0.tmx复制一份命名为1.tmx,大家可以自由发挥修改里面的元素,将第0层的传送点的targetMap设置为1,第一层的传送点设置为0,就可以控制勇士在第0层和第1层之间来回切换了。注意一点,在Teleport.h中,"#include "GameMap.h""要放在类的定义后面,否则会出现编译错误。
让我们看看进入第二个地图后的样子:
最后,附上后期阶段项目源码下载地址:点此下载。本篇结束,我们的魔塔改写就完成了,再次说明的是我用的cocos2d-x版本是2.1.1。请大家自行下载项目源码参考,如有不同的地方以项目源码为准。