CocosCreator3.8.x 解析Tiled1.4.x【瓦片图层、对象图层、图像图层、组图层】的核心原理

一、Cocos Creator 3.8.x 解析 Tiled 图层的核心原理

Cocos Creator 3.8.x 解析 Tiled 图层的本质是:

  1. 读取 .tmx/.tsx 的 XML/JSON 结构(Tiled 导出格式),解析其中的图层元数据(类型、尺寸、属性);
  2. 将解析后的数据映射到 Cocos 内置的 TileMap/TileLayer/ObjectLayer 等类的实例;
  3. 基于渲染管线将瓦片/图像/对象渲染到场景中,同时保留 Tiled 定义的层级、属性、变换等信息。

核心解析流程:

复制代码
Tiled 导出文件 (.tmx) 
  ↓ 解析 XML/JSON 结构
提取图层节点(<layer>/<objectgroup>/<imagelayer>/<group>)
  ↓ 映射到 Cocos 数据结构
TileLayer / ObjectLayer / ImageLayer / GroupLayer 实例
  ↓ 渲染/交互
Cocos 场景中可视化渲染 + 代码可操作

二、各图层解析原理 + 示例代码 + 操作示意图

1. 瓦片图层(Tile Layer)
解析原理
  • Tiled 中 <layer> 标签存储瓦片图层数据,包含 data 节点(瓦片ID数组,支持Base64/CSV编码);
  • Cocos 解析后将瓦片ID映射到瓦片集(Tileset)的纹理坐标,逐瓦片渲染;
  • 支持瓦片的翻转/旋转(Tiled 中通过瓦片ID的高位标记,Cocos 解析后处理纹理UV)。
操作示意图
复制代码
┌─────────────────────────┐
│ Tiled 瓦片图层编辑       │       ┌─────────────────────────┐
│ 1. 图层名:GroundLayer   │       │ Cocos 解析后             │
│ 2. 瓦片坐标(5,5) ID=100 │──────>│ 1. getLayer('GroundLayer')│
│ 3. 瓦片翻转(水平)      │       │ 2. getTileGIDAt(5,5) = 100│
└─────────────────────────┘       │ 3. 自动渲染翻转后的瓦片    │
                                  └─────────────────────────┘
示例代码
typescript 复制代码
import { _decorator, Component, Node, TileMap, TiledTile, Vec2 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('TileLayerDemo')
export class TileLayerDemo extends Component {
    @property(TileMap)
    tileMap: TileMap = null!;

    onLoad() {
        // 1. 解析瓦片图层
        const tileLayer = this.tileMap.getLayer("GroundLayer");
        if (!tileLayer) {
            console.error("瓦片图层不存在");
            return;
        }

        // 2. 读取瓦片基础信息
        const mapSize = this.tileMap.getMapSize(); // 地图总瓦片数
        const tileSize = this.tileMap.getTileSize(); // 单瓦片像素尺寸
        console.log("地图瓦片尺寸:", mapSize.width, "x", mapSize.height);
        console.log("单瓦片像素:", tileSize.width, "x", tileSize.height);

        // 3. 读取指定坐标瓦片(Tiled坐标:x向右,y向下)
        const tileGID = tileLayer.getTileGIDAt(5, 5); // 获取瓦片ID
        console.log("(5,5) 瓦片ID:", tileGID);

        // 4. 读取瓦片翻转/旋转状态(Tiled的翻转标记)
        const tileInfo = tileLayer.getTileInfoAt(5, 5);
        if (tileInfo) {
            console.log("瓦片翻转:", {
                flipX: tileInfo.flipX, // 水平翻转
                flipY: tileInfo.flipY, // 垂直翻转
                rotate: tileInfo.rotate // 旋转(90/180/270)
            });
        }

        // 5. 修改瓦片(动态替换)
        tileLayer.setTileGIDAt(101, 5, 5); // 将(5,5)瓦片替换为ID=101的瓦片

        // 6. 清空瓦片
        tileLayer.removeTileAt(5, 5);
    }
}
2. 对象图层(Object Layer)
解析原理
  • Tiled 中 <objectgroup> 标签存储对象图层,每个 <object> 节点对应一个对象(矩形/椭圆/多边形/点/文本);
  • Cocos 解析后将对象数据封装到 ObjectLayer 类,保留对象的位置、尺寸、自定义属性、类型等;
  • 无原生渲染(仅数据),需开发者根据对象类型创建 Cocos 节点/碰撞体/渲染组件。
操作示意图
复制代码
┌─────────────────────────┐
│ Tiled 对象图层编辑       │       ┌─────────────────────────┐
│ 1. 图层名:Collision    │       │ Cocos 解析后             │
│ 2. 矩形对象:Obstacle1  │──────>│ 1. getObjectLayer('Collision') │
│ 3. 属性:isObstacle=true│       │ 2. 遍历objects数组        │
│ 4. 尺寸:100x50         │       │ 3. 创建BoxCollider2D      │
└─────────────────────────┘       └─────────────────────────┘
示例代码
typescript 复制代码
import { _decorator, Component, Node, TileMap, BoxCollider2D, Vec2, PolygonCollider2D } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('ObjectLayerDemo')
export class ObjectLayerDemo extends Component {
    @property(TileMap)
    tileMap: TileMap = null!;

    onLoad() {
        // 1. 解析对象图层
        const objLayer = this.tileMap.getObjectLayer("CollisionLayer");
        if (!objLayer) return;

        // 2. 遍历所有对象
        objLayer.objects.forEach((obj, index) => {
            console.log(`===== 对象 ${index + 1} =====`);
            console.log("名称:", obj.name);
            console.log("类型:", obj.type); // Tiled中自定义的对象类型
            console.log("位置:", obj.x, obj.y); // 世界坐标
            console.log("尺寸:", obj.width, obj.height); // 仅矩形/椭圆有效
            console.log("自定义属性:", obj.properties); // Tiled中添加的键值对

            // 3. 根据对象类型创建碰撞体
            switch (obj.shape) {
                case 'rect': // 矩形对象
                    const rectCollider = this.node.addComponent(BoxCollider2D);
                    rectCollider.offset = new Vec2(obj.x, obj.y);
                    rectCollider.size = new Vec2(obj.width, obj.height);
                    rectCollider.tag = obj.properties.tag || 0;
                    break;

                case 'polygon': // 多边形对象
                    const polyCollider = this.node.addComponent(PolygonCollider2D);
                    polyCollider.points = obj.polygon.map(p => new Vec2(p.x, p.y));
                    break;

                case 'point': // 点对象(如出生点)
                    console.log("出生点位置:", obj.x, obj.y);
                    // 可创建空节点标记位置
                    const spawnNode = new Node("SpawnPoint");
                    spawnNode.setPosition(obj.x, obj.y);
                    this.node.addChild(spawnNode);
                    break;
            }
        });
    }
}
3. 图像图层(Image Layer)
解析原理
  • Tiled 中 <imagelayer> 标签存储图像图层,包含 <image> 子节点(指定图片路径、偏移、透明度);
  • Cocos 解析后自动创建 Sprite 组件,关联图片资源,保留 Tiled 中设置的偏移、缩放、透明度;
  • 图像图层本质是"整图渲染",区别于瓦片图层的"逐瓦片拼接"。
操作示意图
复制代码
┌─────────────────────────┐
│ Tiled 图像图层编辑       │       ┌─────────────────────────┐
│ 1. 图层名:Background   │       │ Cocos 解析后             │
│ 2. 图片:bg.png         │──────>│ 1. 自动创建Sprite节点     │
│ 3. 偏移:x=10, y=20     │       │ 2. 位置=偏移+地图原点    │
│ 4. 透明度:80%          │       │ 3. opacity=0.8           │
└─────────────────────────┘       └─────────────────────────┘
示例代码
typescript 复制代码
import { _decorator, Component, Node, TileMap, Sprite, Vec2, UITransform } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('ImageLayerDemo')
export class ImageLayerDemo extends Component {
    @property(TileMap)
    tileMap: TileMap = null!;

    onLoad() {
        // 1. 解析图像图层(Cocos将图像图层作为子节点挂载到TileMap节点下)
        const imageLayerNode = this.tileMap.node.getChildByName("BackgroundLayer");
        if (!imageLayerNode) return;

        // 2. 获取Sprite组件(Cocos自动创建)
        const sprite = imageLayerNode.getComponent(Sprite);
        console.log("图像图层图片:", sprite.spriteFrame?.name);

        // 3. 读取/修改图像图层属性(对应Tiled中的设置)
        const uiTransform = imageLayerNode.getComponent(UITransform);
        // 偏移(对应Tiled的offsetx/offsety)
        console.log("图像偏移:", imageLayerNode.position);
        // 透明度(对应Tiled的opacity)
        console.log("原始透明度:", imageLayerNode.opacity);
        imageLayerNode.opacity = 180; // 修改透明度(0-255)

        // 4. 调整图像缩放(模拟Tiled的scale)
        imageLayerNode.setScale(new Vec2(1.2, 1.2));

        // 5. 隐藏/显示图像图层
        imageLayerNode.active = false;
    }
}
4. 组图层(Group Layer)
解析原理
  • Tiled 中 <group> 标签存储组图层,包含多个子图层(瓦片/对象/图像图层);
  • Cocos 解析后将组图层映射为空节点,子图层作为该节点的子节点,保留层级结构;
  • 可通过节点操作控制整个组的可见性、透明度、位置。
操作示意图
复制代码
┌─────────────────────────┐
│ Tiled 组图层编辑         │       ┌─────────────────────────┐
│ 1. 组名:Level1         │       │ Cocos 解析后             │
│  ├─ GroundLayer(瓦片) │──────>│ 1. Level1(空节点)      │
│  └─ Collision(对象)   │       │  ├─ GroundLayer          │
└─────────────────────────┘       │  └─ Collision            │
                                  └─────────────────────────┘
示例代码
typescript 复制代码
import { _decorator, Component, Node, TileMap } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('GroupLayerDemo')
export class GroupLayerDemo extends Component {
    @property(TileMap)
    tileMap: TileMap = null!;

    onLoad() {
        // 1. 解析组图层(Cocos将组图层作为TileMap节点的子节点)
        const groupNode = this.tileMap.node.getChildByName("Level1Group");
        if (!groupNode) return;

        // 2. 控制整个组的可见性
        groupNode.active = false; // 隐藏整个Level1组

        // 3. 遍历组内子图层
        groupNode.children.forEach(child => {
            console.log("组内图层:", child.name);
            // 示例:禁用组内所有碰撞图层
            if (child.name.includes("Collision")) {
                child.active = false;
            }
        });

        // 4. 修改组的整体偏移
        groupNode.setPosition(50, 50);

        // 5. 获取组内指定子图层
        const groundLayer = this.tileMap.getLayer("GroundLayer"); // 跨组也可直接通过名称获取
        if (groundLayer) {
            console.log("组内瓦片图层:", groundLayer.name);
        }
    }
}

三、关键补充说明

  1. 坐标体系对齐
    Tiled 的坐标原点在左上角,y轴向下;Cocos 默认坐标原点在左下角,y轴向上。Cocos 会自动转换 Tiled 坐标,无需手动调整。
  2. 数据编码格式
    Tiled 导出 .tmx 时建议选择 CSV 编码(而非Base64压缩),便于调试;Cocos 3.8.x 兼容两种编码,但CSV更易读取原始瓦片ID。
  3. 示意图可视化建议
    • 在 Tiled 中截图图层编辑界面,标注关键属性(图层名、瓦片ID、对象属性);
    • 在 Cocos 编辑器中截图层级管理器,标注解析后的节点结构,与 Tiled 图层一一对应。

四、调试技巧

  1. 打印完整解析数据:
typescript 复制代码
// 打印TileMap所有图层信息
console.log("所有图层:", this.tileMap.getAllLayers());
// 打印对象图层原始数据
console.log("对象图层原始数据:", JSON.stringify(this.tileMap.getObjectLayer("CollisionLayer")?.objects));
  1. 在 Cocos 编辑器中选中 TileMap 节点,在属性检查器中可直观查看解析后的图层列表、瓦片集关联状态。

以上代码可直接挂载到场景中的 TileMap 节点上运行,需提前在 Tiled 1.4.x 中创建对应类型的图层并导出 .tmx 文件,导入 Cocos 后关联到代码的 tileMap 属性即可。

相关推荐
运维帮手大橙子21 小时前
从基础到体系:我的年度技术学习与实战总结
经验分享·学习
树叶会结冰1 天前
TypeScript---对象:不自在但实在
前端·javascript·typescript
江公望1 天前
tsconfig配置文件增加“esModuleInterop“: true,有什么作用?
typescript
mg6681 天前
0基础开发学习python工具_____用 Python 从零写一个贪吃蛇游戏:完整实现 + 打包成 .exe(附源码)
python·游戏·pygame·python开发
Neozsvc1 天前
Next-DBM ER图模型数据库编辑器
经验分享
中屹指纹浏览器1 天前
指纹浏览器 API 自动化实践:从批量管理到跨系统集成
经验分享·笔记
CodeCaptain1 天前
Cocos Creator 3.8.x 读取 Tiled 1.4.x 原理分析
经验分享·游戏
宝宝单机sop1 天前
微服务资源合集
经验分享
wordbaby1 天前
三个核心概念,帮你彻底打通 TypeScript 泛型
前端·typescript