cocos2dx3.3tilemap縮放滑動(dòng)并且準确點擊對象 - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

您當前位置>首頁 » 新聞資(zī)訊 » 技術(shù)分享 >

cocos2dx3.3tilemap縮放滑動(dòng)并且準确點擊對象

發表時間:2020-10-19

發布人:葵宇科技

浏覽次數:52


之前已經有一篇更基本的tilemap标記了,這兩天用了下(xià)3.3的tilemap發明以前有些器(qì)械又套用不了。所以又寫了一篇劄記,立時感到本身萌萌哒。
完全沒有玩過的童鞋可(kě)以看看基本篇
2. 可(kě)以或許鼠标滑動(dòng) tiledMap
3. 在縮放和(hé)滑動(dòng)的情況下(xià),點擊一個(gè)tile 可(kě)以或許斷定出 實際的格子(zǐ)坐(zuò)标。

縮放和(hé)滑動(dòng)這裡就不再具體說清楚明了,有很多的例子(zǐ),末尾呈上完全代碼。重要說一下(xià)第三條的實現。
1. 可(kě)以或許3倍縮放tiledMap
可(kě)以大年夜圖中(zhōng)看出,我建了一個(gè)points對象組,然後建立了兩個(gè)對象 startPos 和(hé)endPos
startPos 大年夜概覆蓋了 4個(gè)tiled   [0,24] [1,24] [0,25] [1,25]
并且給startPos設置了一個(gè) 自定義屬性:id 。我須要的就是點擊到 膳绫擎4塊tiled的時刻可(kě)以或許 獲取到這個(gè)對象的id值。
[img]http://img.blog.csdn.net/20150105004528937?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ29vZGV2ZW5pbmdiYWJ5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center     [img]http://img.blog.csdn.net/20150105004535239
1.  把tilemapLayer的坐(zuò)标作為偏移量
[img]http://img.blog.csdn.net/20150105004540028
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 和(hé)  pointY , 然則值倒是  (0,296) , 不是等待的(1,768) 溘然有點紛亂 -_- !!了。
直到看了一下(xià)源碼TMXLayer 的getPositionAt才發明,本來這個(gè)(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());
    
<span style="color:#ff0000;">    ret = CC_POINT_PIXELS_TO_POINTS( ret );</span>
    return ret;
}

看一下(xià)宏的定義:
/** @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_FACTOR
On 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()

大年夜源碼可(kě)以看到:
1 . 我們可(kě)以肯定的是tilemap 膳绫擎 pixel : point 的比例是  1 : 1, 而設備膳绫擎卻并不必定。
mac 設備膳绫擎 pixel : point = 1: 1 , iphone Retina 是 2 : 1, 低分辨率就會更大年夜。我們就把這個(gè)比值像素尺寸因子(zǐ)吧
2. 經由過程 CC_POINT_PIXELS_TO_POINTS 可(kě)以或許把 tilemap膳绫擎的坐(zuò)标值轉換成 設備膳绫擎的坐(zuò)标值。
3. 這個(gè)setScale getScale做的昵噜似的工作,然則要區分開來計算。
此外,因為我們的tilemap可(kě)以滑動(dòng)點擊,所以在大年夜觸摸點綴換 tilemap絕對坐(zuò)标的時刻須要額外做兩點:
起首寫了個(gè)函數來讀地圖對象
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. 乘以縮放系數
//參數:觸摸坐(zuò)标
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 "";
}

接下(xià)來再逆推一下(xià)大年夜 觸摸點 轉換到 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;
}

源碼

相關(guān)案例查看更多