首先我们需要知道,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); }
bool HelloLayer::init() { if(!Layer::init()) { return false; } //地图 _tileMap = TMXTiledMap::create("map.tmx"); this->addChild(_tileMap); //精灵 _sprite = Sprite::create("sp.png"); this.addChild(_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); }
void HelloLayer::update(float dt) { this->setViewPoint(_sprite->getPosition()); }
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); };
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); } }
现在我们来判断鼠标点击的是不是障碍物:
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