Cocos2D-X2.2.3学习笔记20(地图系统)

接着上一节的代码来,上次遗留下来的BUG我们一个个的来解决。


首先,我们看向上移动,移动到顶部的时候,我们的主角还能往上移动,而地图一直不动。。。


呃,我们正确的移动方式是,当主角还在屏幕下方的时候,主角移动,等主角移动到中间的时候就开始地图移动,


当地图移动到底端的时候,主角在网上移动


有点乱了。。。。。。


先改代码吧!这个的理解了。逻辑好复杂


1.修改地图和主角移动的BUG


void HelloWorld::menuCallback(CCObject* pSender)
{
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	CCMenuItemImage* item=(CCMenuItemImage*)pSender;
	switch (item->getTag())
	{
	case TOPMENUITEM:
		//地图的高度+地图的Y位置(Y是负数,所以用加而不是减)+一个格子的高度>屏幕的高度
		//这里表示地图还没有移动到最顶部
		if(m_testmap->getContentSize().height+m_testmap->getPositionY()-TMXBLOCKSIZE>visibleSize.height)
		{
			//屏幕高度的一半-地图的Y位置(Y是负数,所以用减)<主角的Y位置
			//如果主角的位置超过了屏幕的中心位置才移动地图
			if(visibleSize.height/2-m_testmap->getPositionY()<m_player->getPositionY())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX(),m_testmap->getPositionY()-TMXBLOCKSIZE));
			}
		    m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()+TMXBLOCKSIZE));
		}
		//主角的Y位置<地图的高度-2个格子的高度
		//因为地图移动到顶部了,所以只能移动主角,这里是判断主角是不是到地图的顶部了
		else if(m_player->getPositionY()<m_testmap->getContentSize().height-2*TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()+TMXBLOCKSIZE));
		}
		break;
	case BUTTOMMENUITEM:
		if(m_testmap->getPositionY()<0)
		{
			if(visibleSize.height/2-m_testmap->getPositionY()>m_player->getPositionY())
			{
				 m_testmap->setPosition(ccp(m_testmap->getPositionX(),m_testmap->getPositionY()+TMXBLOCKSIZE));
			}
		    m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()-TMXBLOCKSIZE));
		}
		else  if(m_player->getPositionY()>TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()-TMXBLOCKSIZE));
		}
		
		break;
	case LEFTMENUITEM:
		if(m_testmap->getPositionX()<0)
		{
			if(visibleSize.width/2-m_testmap->getPositionX()>m_player->getPositionX())
			{
				 m_testmap->setPosition(ccp(m_testmap->getPositionX()+TMXBLOCKSIZE,m_testmap->getPositionY()));
			}
			m_player->setPosition(ccp(m_player->getPositionX()-TMXBLOCKSIZE,m_player->getPositionY()));
		}
		else  if(m_player->getPositionX()>TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX()-TMXBLOCKSIZE,m_player->getPositionY()));
		}
		break;
	case RIGHTMENUITEM:
		if(m_testmap->getContentSize().width+m_testmap->getPositionX()-TMXBLOCKSIZE>visibleSize.width)
		{
			if(visibleSize.width/2-m_testmap->getPositionX()<m_player->getPositionX())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX()-TMXBLOCKSIZE,m_testmap->getPositionY()));
			}
		   m_player->setPosition(ccp(m_player->getPositionX()+TMXBLOCKSIZE,m_player->getPositionY()));
		}
		else if(m_player->getPositionX()<m_testmap->getContentSize().width-2*TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX()+TMXBLOCKSIZE,m_player->getPositionY()));
		}
		break;
	default:
		break;
	}
}

这里的逻辑很复杂,得自己编理解编写。。理解的方式不一样,写发也就不一样

TiledMap地图和主角移动逻辑编写


接下来我们需要解决的是碰撞检测,

当主角遇到障碍物的时候,我们是走不动的,而刚刚看到的是居然可以穿越过去,这个不可以有


2.TMX不同图层进行碰撞检测


OK,我们的NPC最开始是在最坐下角的位置,我们可以按两下向上的按钮,给它向上移动两个格子,到我们标记为红色的位置。。




这时候我们输出的是,

X在第0个格子,Y在第二的格子

我们Cocos2dX用的是OpenGL坐标系统

以左下角为原点的

而Tiled是以左上角为原点的,  此时输出的应该是X:0 Y:17   是从零开始的,所以是17不是18

void HelloWorld::menuCallback(CCObject* pSender)
{
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	CCMenuItemImage* item=(CCMenuItemImage*)pSender;
	/**
	获得NPC在MAP中的第几个格子
	X:这个不用多说了
	Y:因为坐标系统不一样,默认是OpenGL,而TiledMap是屏幕坐标系统,所以应当用地图大小的高度-1-Y
	地图是20X20的格子,m_testmap->getMapSize().height其实就是20
	**/
	CCPoint playerCur=ccp((int)m_player->getPositionX()/TMXBLOCKSIZE,m_testmap->getMapSize().height-1-(int)(m_player->getPositionY()/TMXBLOCKSIZE));
	//CCLOG("X:%f,Y:%f",playerCur.x,playerCur.y);
	//下一个格子
	CCPoint playerNext=playerCur;
	//获得障碍物层
	CCTMXLayer* Obstacles= m_testmap->layerNamed("Obstacles");
	unsigned int GID=0;
	/**
		为了方便大家看的思路清楚,这里分为两个switch写了
		等理解了之后其实搅在一个switch中就可以了的,这个没那么复杂
		复杂的再于判断到底是NPC移动还是地图移动,是否移动到边缘
	**/
	#pragma region NPC的碰撞检测
	switch (item->getTag())
	{
	case TOPMENUITEM:
		playerNext.y-=1;
		if (playerNext.y<0)return;
		/**
		用障碍物层中的tileGIDAt方法来获得其ID
		如果当前层中相应的格子中没东西则返回0
		否则返回ID,至于ID是多少,这个不清楚
		**/
		GID=Obstacles->tileGIDAt(playerNext);
		if (GID)return;
		break;
	case BUTTOMMENUITEM:
		playerNext.y+=1;
		if (playerNext.y>m_testmap->getMapSize().height-1)return;
		GID=Obstacles->tileGIDAt(playerNext);
		if (GID)return;
		break;
	case LEFTMENUITEM:
		playerNext.x-=1;
		if (playerNext.x<0)return;
		GID=Obstacles->tileGIDAt(playerNext);
		if (GID)return;
		break;
	case RIGHTMENUITEM:
		playerNext.x+=1;
		if (playerNext.x>m_testmap->getMapSize().width-1)return;
		GID=Obstacles->tileGIDAt(playerNext);
		if (GID)return;
		break;
	default:
		break;
	}    
#pragma endregion

	#pragma region 这里的逻辑是NPC或地图的移动判断
	switch (item->getTag())
	{
	case TOPMENUITEM:
		//地图的高度+地图的Y位置(Y是负数,所以用加而不是减)+一个格子的高度>屏幕的高度
		//这里表示地图还没有移动到最顶部
		if(m_testmap->getContentSize().height+m_testmap->getPositionY()-TMXBLOCKSIZE>visibleSize.height)
		{
			//屏幕高度的一半-地图的Y位置(Y是负数,所以用减)<主角的Y位置
			//如果主角的位置超过了屏幕的中心位置才移动地图
			if(visibleSize.height/2-m_testmap->getPositionY()<m_player->getPositionY())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX(),m_testmap->getPositionY()-TMXBLOCKSIZE));
			}
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()+TMXBLOCKSIZE));
		}
		//主角的Y位置<地图的高度-2个格子的高度
		//因为地图移动到顶部了,所以只能移动主角,这里是判断主角是不是到地图的顶部了
		else if(m_player->getPositionY()<m_testmap->getContentSize().height-2*TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()+TMXBLOCKSIZE));
		}
		break;
	case BUTTOMMENUITEM:
		if(m_testmap->getPositionY()<0)
		{
			if(visibleSize.height/2-m_testmap->getPositionY()>m_player->getPositionY())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX(),m_testmap->getPositionY()+TMXBLOCKSIZE));
			}
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()-TMXBLOCKSIZE));
		}
		else  if(m_player->getPositionY()>TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX(),m_player->getPositionY()-TMXBLOCKSIZE));
		}

		break;
	case LEFTMENUITEM:
		if(m_testmap->getPositionX()<0)
		{
			if(visibleSize.width/2-m_testmap->getPositionX()>m_player->getPositionX())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX()+TMXBLOCKSIZE,m_testmap->getPositionY()));
			}
			m_player->setPosition(ccp(m_player->getPositionX()-TMXBLOCKSIZE,m_player->getPositionY()));
		}
		else  if(m_player->getPositionX()>TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX()-TMXBLOCKSIZE,m_player->getPositionY()));
		}
		break;
	case RIGHTMENUITEM:
		if(m_testmap->getContentSize().width+m_testmap->getPositionX()-TMXBLOCKSIZE>visibleSize.width)
		{
			if(visibleSize.width/2-m_testmap->getPositionX()<m_player->getPositionX())
			{
				m_testmap->setPosition(ccp(m_testmap->getPositionX()-TMXBLOCKSIZE,m_testmap->getPositionY()));
			}
			m_player->setPosition(ccp(m_player->getPositionX()+TMXBLOCKSIZE,m_player->getPositionY()));
		}
		else if(m_player->getPositionX()<m_testmap->getContentSize().width-2*TMXBLOCKSIZE)
		{
			m_player->setPosition(ccp(m_player->getPositionX()+TMXBLOCKSIZE,m_player->getPositionY()));
		}
		break;
	default:
		break;
	}  
#pragma endregion
}

完整的代码如上,看起来有点凌乱。。。可以收缩起来看,比较清楚




这里差不多就完了,在介绍一个,动态更新地图

3.动态更新地图

Obstacles->setTileGID(46,playerCur);

这里46是什么意思呢??

还记得碰撞检测是获得的GID吗??


一行8个,刚好在第46个。。。

OK,最后附上效果图和源代码




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值