cocos2dx 3.3 tilemap 縮放滑動並且準確點擊對象,cocos2dxtilemap

來源:互聯網
上載者:User

cocos2dx 3.3 tilemap 縮放滑動並且準確點擊對象,cocos2dxtilemap

之前已經有一篇更基礎的tilemap筆記了,這兩天用了下3.3的tilemap發現以前有些東西又套用不了。所以又寫了一篇劄記,頓時感覺自己萌萌噠。

完全沒有玩過的童鞋可以看看基礎篇


主要實現目標: 

1. 能夠3倍縮放tiledMap

2. 能夠滑鼠滑動 tiledMap

3. 在縮放和滑動的情況下,點擊一個tile 能夠判斷出 實際的格子座標。


縮放和滑動這裡就不再詳細解釋了,有很多的例子,末尾呈上完整代碼。主要說一下第三條的實現。

可以看出,我建了一個points對象組,然後建立了兩個對象 startPos 和endPos

startPos 大概覆蓋了 4個tiled   [0,24] [1,24] [0,25] [1,25]

並且給startPos設定了一個 自訂屬性:id 。我需要的就是點擊到 上面4塊tiled的時候能夠 擷取到這個對象的id值。


     





首先寫了個函數來讀地圖對象

void HelloWorld::parseTileMap(){    CCLOG("parseTileMap");    if(_tiledMap == NULL)        return;        _objectsGroup = _tiledMap->getObjectGroup("points");    //tileX 0  tileY 24    ValueMap startPos = _objectsGroup->getObject("startPos");    std::string name = startPos["name"].asString();    float pointX = startPos["x"].asFloat();    float pointY = startPos["y"].asFloat();;    float PointWidth = startPos["width"].asFloat();    float PointHeight = startPos["height"].asFloat();    Size winSize = Director::getInstance()->getWinSize();    Point mapPoint = _tiledMap->getPosition();    Point centerPos = covertTiledPointToCenterPoint(Point(0,24));    Point tilePos = covertPointToTiledPoint(Point(pointX,pointY));    Point tilePos2 = covertPointToTiledPoint(centerPos);}

很順利的拿到startPos對象的 pointX 和  pointY , 但是值卻是  (0,296) , 不是期待的(1,768) 忽然有點淩亂 -_- !!了。

直到看了一下源碼TMXLayer 的getPositionAt才發現,原來這個(0,296) 是已經經過 “解析度轉換“了。

Vec2 TMXLayer::getPositionAt(const Vec2& pos){    Vec2 ret = Vec2::ZERO;    switch (_layerOrientation)    {    case TMXOrientationOrtho:        ret = getPositionForOrthoAt(pos);        break;    case TMXOrientationIso:        ret = getPositionForIsoAt(pos);        break;    case TMXOrientationHex:        ret = getPositionForHexAt(pos);        break;    case TMXOrientationStaggered:        ret = getPositionForStaggeredAt(pos);        break;    }    CCLOG("%f,%f,%f",ret.x,ret.y,CC_CONTENT_SCALE_FACTOR());        ret = <span style="color:#ff0000;">CC_POINT_PIXELS_TO_POINTS</span>( ret );    return ret;}


看一下宏的定義:

/** @def CC_POINT_PIXELS_TO_POINTS Converts a rect in pixels to points */#define CC_POINT_PIXELS_TO_POINTS(__pixels__)                                    \Vec2( (__pixels__).x / CC_CONTENT_SCALE_FACTOR(), (__pixels__).y / CC_CONTENT_SCALE_FACTOR())/** @def CC_CONTENT_SCALE_FACTOROn Mac it returns 1;On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1*/#define CC_CONTENT_SCALE_FACTOR() Director::getInstance()->getContentScaleFactor()


從源碼可以看到:

1 . 我們可以確定的是tilemap 上面 pixel : point 的比例是  1 : 1, 而裝置上面卻並不一定。

mac 裝置上面 pixel : point = 1: 1 , iphone Retina 是 2 : 1, 低解析度就會更大。我們就把這個比值像素尺寸因子吧

2. 通過 CC_POINT_PIXELS_TO_POINTS 能夠把 tilemap上面的座標值轉換成 裝置上面的座標值。

3. 這個setScale getScale做的是類似的事情,但是要區分開來計算。


此外,因為我們的tilemap可以滑動點擊,所以在從觸摸點轉換 tilemap絕對座標的時候需要額外做兩點:

1.  把tilemapLayer的座標作為位移量

bool HelloWorld::onTouchBegan(Touch *touch, Event  *event){    CCLOG("HelloWorld::onTouchBegan");    Point touchPoint = touch->getLocation();    Point mapPoint = _tiledMap->getPosition();  <span style="color:#ff0000;">  Point realPoint = touchPoint - mapPoint;</span>    Point tilePoint = covertPointToTiledPoint(realPoint);    CCLOG("tilePoint x:%f y:%f",tilePoint.x,tilePoint.y);        tryGetObjectPropertyByPosition(realPoint);    return true;}


2. 乘以縮放係數
//參數:觸摸座標string HelloWorld::tryGetObjectPropertyByPosition(Point position){    float scale = _tiledMap->getScale();    float factor = CC_CONTENT_SCALE_FACTOR();    <span style="color:#ff0000;">    float realPointX = position.x / scale;    float realPointY = position.y / scale;</span>        for (auto item : _objectsGroup->getObjects())    {        ValueMap curObject = item.asValueMap();        float pointX = curObject["x"].asFloat();        float pointY = curObject["y"].asFloat();;        float PointWidth = curObject["width"].asFloat();        float PointHeight = curObject["height"].asFloat();                if(realPointX >= pointX and realPointX <= pointX + PointWidth           and realPointY >= pointY and realPointY <= pointY + PointHeight)        {            string objectId = curObject["id"].asString();            CCLOG("HelloWorld:tryGetObjectPropertyByPosition: %s",objectId.c_str());            return objectId;        }    }    return "";}


接下來再逆推一下從 觸摸點 轉換到 tilemapPoint 的方法就非常簡單了

Point HelloWorld::covertTiledPointToCenterPoint(Point p){    float scale = _tiledMap->getScale();    float factor = CC_CONTENT_SCALE_FACTOR();        CCLOG("HelloWorld::covertTiledPointToCenterPoint scale:%f factor:%f",scale,factor);        int offsetX = _tiledMap->getTileSize().width / (2 * factor);    int offsetY = _tiledMap->getTileSize().height / (2 * factor);    TMXLayer* layer = _tiledMap->layerNamed("background");    Point point = layer->getPositionAt(p);        point = Point(point.x  + offsetX,point.y - offsetY);    point = Point(point.x * scale, point.y * scale);    return point;}

源碼







聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.