cocos2dx 3.x Tiled的程序控制

本文介绍使用Cocos2d-x实现地图滚动及角色与地图障碍物的碰撞处理方法,包括对象层的加载、地图滚动效果的实现及碰撞检测的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

From: http://blog.csdn.net/lengxue789/article/details/38399995

1. Tiled 对象层

TMXObjectGroup 对象存放了对象层的所有对象,通过getObjectGroup函数获取指定名称的对象层,还可以通过getObject获得具体的对象。

  1. //加载对象层  
  2. auto objGroup = map->getObjectGroup("objects");  
  3. //加载玩家坐标  
  4. auto playerPointDic = objGroup->getObject("PlayerPoint");  
  5. float playerX = playerPointDic.at("x").asFloat();  
  6. float playerY = playerPointDic.at("y").asFloat();  
	//加载对象层
	auto objGroup = map->getObjectGroup("objects");
	//加载玩家坐标
	auto playerPointDic = objGroup->getObject("PlayerPoint");
	float playerX = playerPointDic.at("x").asFloat();
	float playerY = playerPointDic.at("y").asFloat();

2. 地图随主角的滚动

每当主角的坐标改变时,地图坐标随着改变。

  1. auto parent = (Layer*)getParent();  
  2.   
  3. //地图方块的数量  
  4. Size mapTiledNum = m_map->getMapSize();  
  5.   
  6. //地图单个格子的大小  
  7. Size tiledSize = m_map->getTileSize();  
  8.   
  9. //地图的大小  
  10. Size mapSize = Size::Size(mapTiledNum.width*tiledSize.width,mapTiledNum.height*tiledSize.height);  
  11.   
  12. //屏幕大小  
  13. Size visibleSize = Director::getInstance()->getVisibleSize();  
  14.   
  15. //主角坐标  
  16. auto spritePos = getPosition();  
  17.   
  18. //如果主角坐标小于屏幕的一半,则取屏幕中点坐标,否则取主角的坐标  
  19. float x = MAX(spritePos.x,visibleSize.width/2);  
  20. float y = MAX(spritePos.y,visibleSize.height/2);  
  21.   
  22. //如果X、Y的坐标大于右上角的极限值,则取极限值的坐标(极限值是指不让地图超过屏幕造成出现黑边的极限坐标)  
  23. x = MIN(x,mapSize.width - visibleSize.width/2);  
  24. y = MIN(y,mapSize.height - visibleSize.height/2);  
  25.   
  26. //目标点  
  27. auto destPos = Point(x,y);  
  28.   
  29. //屏幕中点  
  30. auto centerPos = Point(visibleSize.width/2,visibleSize.height/2);  
  31.   
  32. auto viewPos = centerPos.operator-(destPos);  
  33.   
  34. parent->setPosition(viewPos);  
	auto parent = (Layer*)getParent();

	//地图方块的数量
	Size mapTiledNum = m_map->getMapSize();

	//地图单个格子的大小
	Size tiledSize = m_map->getTileSize();

	//地图的大小
	Size mapSize = Size::Size(mapTiledNum.width*tiledSize.width,mapTiledNum.height*tiledSize.height);

	//屏幕大小
	Size visibleSize = Director::getInstance()->getVisibleSize();

	//主角坐标
	auto spritePos = getPosition();

	//如果主角坐标小于屏幕的一半,则取屏幕中点坐标,否则取主角的坐标
	float x = MAX(spritePos.x,visibleSize.width/2);
	float y = MAX(spritePos.y,visibleSize.height/2);

	//如果X、Y的坐标大于右上角的极限值,则取极限值的坐标(极限值是指不让地图超过屏幕造成出现黑边的极限坐标)
	x = MIN(x,mapSize.width - visibleSize.width/2);
	y = MIN(y,mapSize.height - visibleSize.height/2);

	//目标点
	auto destPos = Point(x,y);
	
	//屏幕中点
	auto centerPos = Point(visibleSize.width/2,visibleSize.height/2);

	auto viewPos = centerPos.operator-(destPos);

	parent->setPosition(viewPos);

3. 主角遇到障碍物如何处理

添加障碍物,参考笨木头的博客,http://www.benmutou.com/archives/32

判断前面是否有障碍物,3.x的版本和2.0版本不同。

  1. void Player::setTagPosition(int x,int y){  
  2.   
  3.     Size spriteSize = m_sprite->getContentSize();  
  4.     auto dstPos = Point( x + spriteSize.width/2,y);  
  5.   
  6.     //获取当前主角前方坐标在地图中的格子位置  
  7.     auto tiledPos = tileCoordForPosition(Point(dstPos.x,dstPos.y));  
  8.     int tiledGid = meta->getTileGIDAt(tiledPos);  
  9.   
  10.     if (tiledGid != 0)  
  11.     {  
  12.         auto propertiesDict = m_map->getPropertiesForGID(tiledGid).asValueMap();  
  13.         if (!propertiesDict.empty()) {  
  14.             auto prop = propertiesDict["Collidable"].asString();  
  15.             if("true" == prop){  
  16.                 x -=1;  
  17.                 y -=1;  
  18.             }  
  19.   
  20.             auto propStar = propertiesDict["star"].asString();  
  21.             if("true" == propStar){  
  22.                 auto barrier = m_map->getLayer("barrier");  
  23.                 barrier->removeTileAt(tiledPos);  
  24.             }  
  25.   
  26.             auto propWin = propertiesDict["win"].asString();  
  27.             if("true" == propWin){  
  28.                 Director::getInstance()->replaceScene(WinScene::createScene());  
  29.             }  
  30.   
  31.   
  32.         }  
  33.     }  
  34.   
  35.     Entity::setTagPosition(x,y);  
  36.     setViewPointByPlayer();  
  37. }  
void Player::setTagPosition(int x,int y){

	Size spriteSize = m_sprite->getContentSize();
	auto dstPos = Point( x + spriteSize.width/2,y);

	//获取当前主角前方坐标在地图中的格子位置
	auto tiledPos = tileCoordForPosition(Point(dstPos.x,dstPos.y));
	int tiledGid = meta->getTileGIDAt(tiledPos);

	if (tiledGid != 0)
	{
		auto propertiesDict = m_map->getPropertiesForGID(tiledGid).asValueMap();
		if (!propertiesDict.empty()) {
			auto prop = propertiesDict["Collidable"].asString();
			if("true" == prop){
				x -=1;
				y -=1;
			}

			auto propStar = propertiesDict["star"].asString();
			if("true" == propStar){
				auto barrier = m_map->getLayer("barrier");
				barrier->removeTileAt(tiledPos);
			}

			auto propWin = propertiesDict["win"].asString();
			if("true" == propWin){
				Director::getInstance()->replaceScene(WinScene::createScene());
			}


		}
	}

	Entity::setTagPosition(x,y);
	setViewPointByPlayer();
}

getTileGIDAt 函数:通过指定的tile坐标获取对应的tile grid,也返回对应的tile flags 这个方法要求tile地图之前没有被释放掉(如,不能调用layer->releaseMap())

getPropertiesForGID函数:通过GID获取对应的属性字典(properties dictionary)

asValueMap函数 将value转为valueMap,之后可以通过name得到属性值。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值