在使用cocos2d-x编程时,常常会用到的一个功能便是如何实现地图跟随精灵(角色)的移动而卷动,特别是对于跑酷类游戏来说,这样就会让精灵一直处于屏幕的可见范围内。在这里介绍两种最基本的方法
1.第一种方法
第一种方法实现起来比较简单,主要的思路是因为精灵是处于地图之上的,因此,我们移动精灵是相对于地图的,移动精灵之后得到的坐标也是相对于父节点的坐标,将其转为世界坐标体系判断其X坐标有没有超出屏幕宽度的一半,如果有,就将地图的坐标反方向移动与精灵同等大小的距离,此时游戏表现出来的结果就是精灵一直在在屏幕的正中央,而地图却在不停的向后卷动。
代码如下:
#define winSize CCDirector::sharedDirector()->getWinSize()
//向右移动精灵,dt:每次帧循环持续的时间
//speed,精灵移动的速度
setPositionX(getPositionX() + dt * speed);
//得到精灵相对于地图map的坐标
Point ptInMap = this->getPosition();
//将精灵由节点坐标转换为世界坐标
Point ptInWorld = m_map->convertToWorldSpace(ptInMap);
//得到窗口宽度的一半
float width = winSize.width / 2;
//判断精灵坐标是否超过了窗口宽度的一半,如果是,向左移动地图
if (ptInWorld.x > width )
{
//向左移动地图,移动的距离与精灵相同,方向相反
m_map->setPositionX(getMap()->getPositionX() - dt *speed);
}
这样就实现了最简单的地图卷动,但是这种方法也会有一个问题,那就是因为精灵会一直在地图上向右移动,而地图却一直在向左移动,会导致给人的视觉是精灵一直在屏幕的中央,而且地图的最右边会一直移动到屏幕的中央,产生黑边。因此在地图的最右边到达屏幕的最右边时应当做个判断,此时不移动地图,在移动地图的if语句里添加如下代码:
if(m_map->getPositionX()<= winSize.width)
{
//当地图的最右边相对于屏幕的坐标小于屏幕的宽度时,直接返回,不卷动地图
return;
}
2.第二种方法:
第二种方法是《游戏开发之旅》这本书所介绍的,其代码如下:
Layer *parent = (Layer *)getParent();
//地图方块数量
Size mapTiledNum = m_map->getMapSize();
//地图单个格子大小
Size tiledSize = m_map->getTileSize();
//地图大小
Size mapsize = Size(
mapTiledNum.width * tiledSize.width,
mapTiledNum.height * tiledSize.height);
//屏幕大小
Size visiableSize = Director::getInstance()->getVisibleSize();
//主角坐标
Point spritePos = getPosition();
//如果主角坐标小于屏幕的一半,则取屏幕中点坐标,
//否则取主角的坐标
float x = std::max(spritePos.x, visiableSize.width / 2);
float y = std::max(spritePos.y, visiableSize.height / 2);
//如果X、Y的坐标大于右上角的极限值,则取极限值的坐标
//极限值是指不让地图超出屏幕造成出现黑边的极限坐标
x = std::min(x, mapsize.width - visiableSize.width / 2);
y = std::min(y, mapsize.height - visiableSize.height / 2);
//目标点
Point destPos = Point(x, y);
//屏幕中点
Point centerPos = Point(visiableSize.width / 2, visiableSize.height / 2);
//计算屏幕中点和所要移动的目的点之间的距离
Point viewPos = centerPos - destPos;
parent->setPosition(viewPos);