改写《魔塔》中篇02:重构代码之分离游戏地图类

      写在前面:中期阶段我们只是按照书上的方式来介绍重构代码的过程,由于版本等原因,粘贴出来的代码已经不符合我们的需要。所以具体改动的代码以中期阶段项目里面的源码文件为准,项目源码下载请移步改写《魔塔》中篇06:善后工作和注意事项(附:中期阶段项目下载)。还有我们对原书中的项目进行了一些改动,包括用CCArray替换了CCMutableArray,增加了用于勇士初始化的getSpriteFrame方法等,因此,大家要注意项目源码改动的地方,并且留意文档注释。 

      我们已经将HelloWorldScene.cpp中的代码分离成GameScene和GameLayer两部分。可以看出GameScene类的功能已经相对单一了,但GameLayer类仍然内容驳杂。下面来想办法继续拆分GameLayer类。目前游戏主界面包含3个对象,即地图,勇士和控制按钮(关闭按钮和方向按钮)。因此可以将GameLayer中的方法按这3大类进行划分。

   (1)地图类负责TMX地图的各项初始化操作以及Tilemap坐标系和cocos2d-x坐标系之间的转换。

   (2)勇士类负责行走动画的创建,在地图上移动以及碰撞检测。

   (3)控制层则包括关闭按钮和方向按钮的逻辑。

       先分离地图对象。我们的游戏地图类在CCTMXTiledMap功能基础上,添加了额外的初始化操作:包括方便地获取各个层,开启纹理抗锯齿,以后可能会有的敌人以及NPC属性的读取。另外,Tilemap和cocos2d-x坐标系的转换以及碰撞检测也可以放在地图类中。现在,新建一个GameMap类,继承自CCTMXTiledMap,然后将需要实现的方法写在头文件里,具体代码如下:

#ifndef __GAME_MAP_H__
#define __GAME_MAP_H__

#include "MTGame.h"
typedef enum
{
	kNone = 1,//可以通行
	kWall,//墙
	kEnemy,//敌人
} CollisionType;//碰撞类型

using namespace cocos2d;

//继承自CCTMXTiledMap
class GameMap:public cocos2d::CCTMXTiledMap
{
	//只读变量,获取地板层和墙壁层
	CC_PROPERTY_READONLY(CCTMXLayer*,floorLayer,FloorLayer);
	CC_PROPERTY_READONLY(CCTMXLayer*,wallLayer,WallLayer);
public:
	GameMap(void);
	~GameMap(void);
	//静态方法,用于生成GameMap实例
	static GameMap* gameMapWithTMXFile(const char* tmxFile);
	//TiledMap和cocos2d-x坐标系相互转换的方法
	CCPoint tileCoordForPosition(CCPoint position);
	CCPoint positionForTileCoord(CCPoint tileCoord);
protected:
	//TiledMap额外的初始化方法
	void extraInit();
	//开启各图层的纹理抗锯齿
    void enableAnitiAliasForEachLayer();
};

#endif

      在类的开始我们使用了CC_PROPERTY_READONLY宏,这是cocos2d-x引擎内嵌的宏,可以方便地声明变量的getset方法,具体用法参见CCPlateformMacros.h。这里声明了两个protectedCCTMXLayer指针类型的变量,用来获取地板层和墙壁层。在cpp文件中,需要自己实现getter方法:

//返回地板层
CCTMXLayer* GameMap::getFloorLayer()
{
	return floorLayer;
}

//返回墙壁层
CCTMXLayer* GameMap::getWallLayer()
{
	return wallLayer;
}

    静态方法gameMapWithTMXFile用于生成GameMap实例。它遵循了cocos2d-x生成对象的规范:new一个对象,调用其init方法,设置对象为autorelease。具体代码如下:

//静态方法,用于生成GameMap实例
GameMap* GameMap::gameMapWithTMXFile(const char* tmxFile)
{
	//new一个对象
	GameMap* pRet=new GameMap();
	//调用init方法
	if(pRet->initWithTMXFile(tmxFile))
	{
		//调用额外的init方法
		pRet->extraInit();
		//将实例放入autorerelease池,统一由引擎控制对象的生命周期
		pRet->autorelease();
		return pRet;
	}
	CC_SAFE_DELETE(pRet);
	return NULL;
}

    在gameMapWithTMXFile中除了调用CCTMXTiledMap自有的initWithTMXFile方法以外,还调用了我们自己定义的extraInit方法,用于进行一些额外的初始化操作。

//TiledMap额外的初始化方法
void GameMap::extraInit()
{
	//开启各个图层的纹理抗锯齿
	enableAnitiAliasForEachLayer();
	//初始化地板层和墙壁层对象
	floorLayer=this->layerNamed("floor");
	wallLayer=this->layerNamed("wall");
}
enableAnitiAliasForEachLayer方法用于开启TiledMap中所有层的纹理抗锯齿效果:
void GameMap::enableAnitiAliasForEachLayer()
{
	CCArray* pChildrenArray=this->getChildren();
	CCSpriteBatchNode* child=NULL;
	CCObject* pObject=NULL;
	//遍历Tilemap的所有图层
	CCARRAY_FOREACH(pChildrenArray,pObject)
	{
	    child=(CCSpriteBatchNode*)pObject;
		if(!child)
			break;
		//给图层的纹理开启抗锯齿
		child->getTexture()->setAntiAliasTexParameters();
	}
}

    tileCoordForPositionpositionForTileCoordcheckCollision方法基本与前面HelloWorld中的实现一致,这里不再赘述(后面把checkCollision方法放在了新建的勇士类里)。最后在GameLayer中,只需要调用GameMapgameMapWithTMXFile方法就可以很方便地创建游戏地图了,具体代码如下:

map=GameMap::gameMapWithTMXFile("0.tmx");
addChild(map);





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值