首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Cocos2d-x 像素座標轉瓦片地圖網格座標:CCTMXTiledMap 正確轉換方法

     編輯:程式設計綜合問答

問題背景

觸摸點為屏幕像素座標,需轉換為 TMX 地圖的網格座標 (tile coordinates) 以檢測碰撞層 (Meta Layer) 是否可通行。

核心轉換邏輯

關鍵步驟:

  1. 將觸摸點轉換為地圖節點座標系 (convertToNodeSpace)。
  2. 考慮地圖錨點 (通常為左下角) 和瓦片尺寸。
  3. **Y 軸翻轉**:屏幕座標 Y 向下增長,TMX 地圖數組索引 Y 通常向上增長 (第 0 行在底部)。

標準轉換函數


// 在繼承自 CCTMXTiledMap 的類中,或傳入 map 節點
Vec2 tileCoordForPosition(Vec2 position) {
    // 1. 轉換到地圖節點座標系
    Vec2 nodePos = this->convertToNodeSpace(position);
    
    // 2. 獲取地圖屬性
    Size mapSize = this->getMapSize();      // 瓦片數 (寬, 高)
    Size tileSize = this->getTileSize();    // 單個瓦片像素尺寸
    
    // 3. 計算網格索引
    int x = static_cast(nodePos.x / tileSize.width);
    int y = static_cast((mapSize.height * tileSize.height - nodePos.y) / tileSize.height);
    // 關鍵:mapSize.height * tileSize.height = 地圖總高度 (像素)
    // nodePos.y 從下往上,需用總高度減去得到從上往下的行號
    
    // 4. 邊界檢查
    x = MAX(0, MIN(x, static_cast(mapSize.width) - 1));
    y = MAX(0, MIN(y, static_cast(mapSize.height) - 1));
    
    return Vec2(x, y);
}

使用示例:檢測 Meta 層碰撞


bool isPositionWalkable(Vec2 touchPos) {
    Vec2 tileCoord = tileCoordForPosition(touchPos);
    
    // 獲取 Meta 層
    TMXLayer *metaLayer = this->getLayer("Meta");
    if (!metaLayer) return true; // 無碰撞層視為可通行
    
    // 獲取該網格的精靈 (GID > 0 表示有碰撞瓦片)
    Sprite *tileSprite = metaLayer->getTileAt(tileCoord);
    // 或直接獲取 GID
    int gid = metaLayer->getTileGIDAt(tileCoord);
    
    return gid == 0; // GID 為 0 表示空瓦片,可通行
}

常見錯誤對照

錯誤做法正確做法後果
直接用 position.x / tileWidth先 convertToNodeSpace父節點縮放/旋轉/位移導致座標錯誤
Y 軸不翻轉mapHeight * tileHeight - nodePos.y點擊底部檢測到頂部行,垂直鏡像
用 tileWidth 計算 Y用 tileHeight非正方形瓦片時行號錯誤
無邊界檢查clamp 到 [0, mapSize-1]越界訪問 Crash 或邏輯錯誤

進階:等距/六邊形地圖

上述為**正交地圖** (Orthogonal)。等距地圖 (Isometric) 轉換公式不同:


// 等距地圖座標轉換 (參考)
float x = (nodePos.x / tileSize.width + (mapSize.height - nodePos.y / tileSize.height)) / 2;
float y = (mapSize.height - nodePos.y / tileSize.height - nodePos.x / tileSize.width) / 2;

六邊形地圖需根據具體朝向 (pointy-top/flat-top) 推導公式。

總結

核心公式:
x = nodePos.x / tileWidth
y = (mapHeight * tileHeight - nodePos.y) / tileHeight
務必:轉節點座標、Y軸翻轉、邊界檢查。封裝為工具函數復用,避免重複造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved