展会信息港展会大全

cocos2d-x 使用tmx地图总结,cocos2d-xtmx 1.地图随主角移动 2.地图拖动 3.地图缩放 4.碰撞检测
来源:互联网   发布日期:2015-09-28 15:41:52   浏览:1979次  

导读: cocos2d-x 使用tmx地图总结,cocos2d-xtmx 首先我们需要知道,tmx地图的坐标为格子坐标,左上角为原点(0,0),而cocos里面一般使用opengl坐标系,即左下角为原...

cocos2d-x 使用tmx地图总结,cocos2d-xtmx

首先我们需要知道,tmx地图的坐标为格子坐标,左上角为原点(0,0),而cocos里面一般使用opengl坐标系,即左下角为原点(0,0)。

我们可以这样子来转换tmx地图和opengl的坐标:

Point HelloLayer::tiledCoorForPosition(const Point& position)//转成格子坐标

{

Size mapSize = _tiledMap->getMapSize();

Size tileSize = _tiledMap->getTileSize();

int x = (position.x ) / tileSize.width;

int y = (mapSize.height * tileSize.height - position.y ) / tileSize.height;

return Point(x,y);

}

Point HelloLayer::positionForTiledCoor(const Point& tiledCoor)//转成oepngl坐标

{

Size mapSize = _tiledMap->getMapSize();

Size tileSize = _tiledMap->getTileSize();

int x = tiledCoor.x * tileSize.width + tileSize.width / 2;

int y = (mapSize.height * tileSize.height) - (tiledCoor.y * tileSize.height + tileSize.height / 2);

return Point(x,y);

}

layer的锚点为(0,0),tmx地图的锚点默认是(0,0),如果我们在layer中添加tmx地图,比如这样子:

bool HelloLayer::init()

{

if(!Layer::init())

{

return false;

}

//地图

_tileMap = TMXTiledMap::create("map.tmx");

this->addChild(_tileMap);

//精灵

_sprite = Sprite::create("sp.png");

this.addChild(_sprite);

}

那么我们现在来依次实现如下功能:

1.地图随主角移动

以sprite为焦点来调整地图的位置:

void HelloLayer::setViewPoint(const Point& point)

{

Size winSize = Director::getInstance()->getWinSize();

int x = MAX(point.x, winSize.width / 2);

int y = MAX(point.y, winSize.height / 2);

x = MIN(x, _tiledMap->getMapSize().width * _tiledMap->getTileSize().width - winSize.width / 2);

y = MIN(y, _tiledMap->getMapSize().height * _tiledMap->getTileSize().height - winSize.height / 2);

Point actualPoint(x,y);

Point centerOfView(winSize.width / 2, winSize.height / 2);

Point viewPoint = centerOfView - actualPoint;

_tiledMap->setPosition(viewPoint);

}

然后不断的在update函数中不断的检测sprite的位置并设置地图位置就可以了

void HelloLayer::update(float dt)

{

this->setViewPoint(_sprite->getPosition());

}

2.地图拖动

地图移动主要是在onTouchMoved里面判断两个点的偏移向量vec,然后判断边界值避免出现黑边,具体如下

listener->onTouchMoved = [&] (Touch* touch, Event* event)

{

Point prePos = touch->getPreviousLocation();

Point curPos = touch->getLocation();

Point vec = curPos - prePos;

Point mapPos = _tiledMap->getPosition();

Point viewPos = mapPos + vec;

Size winSize = Director::getInstance()->getWinSize();

Size mapSize = _tiledMap->getMapSize();

Size tileSize = _tiledMap->getTileSize();

//若x坐标值超过边界值,则去掉x的偏移

if(viewPos.x <winSize.width - mapSize.width * tileSize.width || viewPos.x > 0 )

{

viewPos.x -= vec.x;

}

//同理,若y坐标值超过边界值,则去掉y的偏移

if(viewPos.y < winSize.height - mapSize.height * tileSize.height || viewPos.y >0 )

{

viewPos.y -= vec.y;

}

_tiledMap->setPosition(viewPos);

};

3.地图缩放

下面来实现地图的放大功能,具体为点击一个点p1,然后以p1为屏幕的焦点不断去放大地图

listener->onTouchBegan = [this] (Touch* touch, Event* event)

{

//点击位置p1

Point touchLocation = _tiledMap->convertTouchToNodeSpace(touch);

_touchPos = touchLocation;

//缩放

_tiledMap->runAction(ScaleBy::create(1.0f,1.2f,1.2f,1.0f));

this->scheduleUpdate();

return true;

}

void HelloLayer::update(float dt)

{

//缩放的同时不断更新焦点p1的位置(因为地图放大,地图中的点的坐标也要相应放大)

float scale = _tiledMap->getScale();

Point viewPos(scale * _touchPos.x,scale * _touchPos.y);

//根据p1不断设置地图的位置

this->setViewPointByScale(viewPos,scale);

}

void HelloLayer::setViewPointByScale(const Point& point,float scale)

{

Size winSize = Director::getInstance()->getWinSize();

int x = MAX(point.x, winSize.width / 2);

int y = MAX(point.y, winSize.height / 2);

//需要注意的是,地图放大后,mapSize和tileSize并没有变大,所以判断边界的时候我们需要手动 * scale

x = MIN(x, _tiledMap->getMapSize().width * _tiledMap->getTileSize().width * scale - winSize.width / 2);

y = MIN(y, _tiledMap->getMapSize().height * _tiledMap->getTileSize().height * scale - winSize.height / 2);

Point actualPoint(x,y);

Point centerOfView(winSize.width / 2, winSize.height / 2);

Point viewPoint = centerOfView - actualPoint;

_tiledMap->setPosition(viewPoint);

}

以上是一个比较简单的思路,比如我们要实现双指缩放,可以参照上面的思路这样子做:

listener->onTouchesBegan = [&] (const std::vector<Touch*>& touches, Event* event)

{

if(touches.size() >= 2)

{

Point p1 = _tiledMap->convertTouchToNodeSpace(touches[0]);

Point p2 = _tiledMap->convertTouchToNodeSpace(touches[1]);

//算出亮点距离,保存到类变量中

_distance = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

}

return true;

}

listener->onTouchesMoved = [&] (const std::vector<Touch*> &touches, Event* event)

{

if(touches.size() >= 2)

{

Point p1 = _tiledMap->convertTouchToNodeSpace(touches[0]);

Point p2 = _tiledMap->convertTouchToNodeSpace(touches[1]);

//算出缩放倍数,并保存新的距离

float new_distance = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

float scale = new_distance / _distance;

_distance = new_distance;

//取p1和p2中点,缩放地图并设置屏幕焦点

Point pCenter ((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);

_tiledMap->setScale(scale);

this->setViewPointByScale(pCenter,scale);

}

}

4.碰撞检测

碰撞检测比较简单,现有地图如下:(因为正在看A*算法,所以就拿这地图举例了,A*寻路算法原文地址如下

http://blog.csdn.net/akof1314/article/details/19333255)

现在我们来判断鼠标点击的是不是障碍物:

listener->onTouchBegan = [this] (Touch* touch, Event* event)

{

Point touchLocation = _tiledMap->convertTouchToNodeSpace(touch);

Point tileCoord = this->tiledCoorForPosition(touchLocation);

if(this->isWallAtTileCoord(tileCoord))//检测是否为墙壁

{

CCLOG("isWall");

}

}

bool HelloLayer::isWallAtTileCoord(const Point &tileCoord) const

{

//先获取格子的gid值,再获取属性值

int gid = _bgLayer->getTileGIDAt(tileCoord);

Value properties = _tiledMap->getPropertiesForGID(gid);

if (properties.isNull())

{

return false;

}

return properties.asValueMap().find("Wall") != properties.asValueMap().end();

}

恩,大致就这些了。

转载请注明出处:http://blog.csdn.net/shun_fzll/article/details/39480393

Cocos2d-x 怎获取tmx地图上的事件对象坐标?

要找高手帮你解答下,百度搜下:红孩儿 教程,会找到你想要的答案。

赞助本站

人工智能实验室

相关热词: 编程 软件开发 应用开发

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港