【提问】TiledMap 设置了图块碰撞编辑如何在代码中获取?

问一个TiledMap相关的问题:
我在编辑地图的时候,想做一个障碍物,但是障碍物有一部分是空白的。
而TiledMap中自带了图块碰撞编辑器,我用该编辑器编辑了可碰撞的区域后,目前不清楚怎么获取到该图块的碰撞区域。
所以我想知道一下如何在代码中获取到对应的可碰撞区域?
麻烦知道的童鞋告知一下,感激不尽。
示意图如下:

@jare 听说@jare就能解决问题

引擎没有实现 对引擎进行一下扩展可以获取到
新建一个 js 脚本 复制下面的代码


function strToColor (value) {
    if (!value) {
        return cc.color(0, 0, 0, 255);
    }
    value = (value.indexOf('#') !== -1) ? value.substring(1) : value;
    if (value.length === 8) {
        let a = parseInt(value.substr(0, 2), 16) || 255;
        let r = parseInt(value.substr(2, 2), 16) || 0;
        let g = parseInt(value.substr(4, 2), 16) || 0;
        let b = parseInt(value.substr(6, 2), 16) || 0;
        return cc.color(r, g, b, a);
    } else {
        let r = parseInt(value.substr(0, 2), 16) || 0;
        let g = parseInt(value.substr(2, 2), 16) || 0;
        let b = parseInt(value.substr(4, 2), 16) || 0;
        return cc.color(r, g, b, 255);
    }
}

// 扩展导出 m_type (对象类型)
function getPropertyList (node, map) {
    let res = [];
    let properties = node.getElementsByTagName("properties");
    for (let i = 0; i < properties.length; ++i) {
        let property = properties[i].getElementsByTagName("property");
        for (let j = 0; j < property.length; ++j) {
            res.push(property[j]);
        }
    }

    map = map || {};
    for (let i = 0; i < res.length; i++) {
        let element = res[i];
        let name = element.getAttribute('name');
        let type = element.getAttribute('type') || 'string';

        let value = element.getAttribute('value');
        if (type === 'int') {
            value = parseInt(value);
        }
        else if (type === 'float') {
            value = parseFloat(value);
        }
        else if (type === 'bool') {
            value = value === 'true';
        }
        else if (type === 'color') {
            value = strToColor(value);
        }

        map[name] = value;
    }

    return map;
}

cc.TiledMap.prototype._tileObjectGroups = [];
if(!CC_EDITOR){
    cc.js.getset(cc.TiledMap.prototype,"tileObjectGroups",function(){ return this._tileObjectGroups;});
}

// let _buildWithMapInfo = cc.TiledMap.prototype._buildWithMapInfo;
cc.TiledMap.prototype._buildWithMapInfo = function(mapInfo) {
        this._mapInfo = mapInfo;
        this._mapSize = mapInfo.getMapSize();
        this._tileSize = mapInfo.getTileSize();
        this._mapOrientation = mapInfo.orientation;
        this._properties = mapInfo.properties;
        this._tileProperties = mapInfo.getTileProperties();
        this._imageLayers = mapInfo.getImageLayers();
        this._animations = mapInfo.getTileAnimations();
        this._tileObjectGroups = mapInfo._tileObjectGroups;
        this._tilesets = mapInfo.getTilesets();

        let tilesets = this._tilesets; 
        this._textures.length = 0;

        let totalTextures = [];
        for (let i = 0, l = tilesets.length; i < l; ++i) {
            let tilesetInfo = tilesets[i];
            if (!tilesetInfo || !tilesetInfo.sourceImage) continue;
            this._textures[i] = tilesetInfo.sourceImage;
            totalTextures.push(tilesetInfo.sourceImage);
        }

        for (let i = 0; i < this._imageLayers.length; i++) {
            let imageLayer = this._imageLayers[i];
            if (!imageLayer || !imageLayer.sourceImage) continue;
            totalTextures.push(imageLayer.sourceImage);
        }

        cc.TiledMap.loadAllTextures (totalTextures, function () {
            this._buildLayerAndGroup();
        }.bind(this));
}





cc.TMXMapInfo.prototype._tileObjectGroups = {};
let _initWithXML = cc.TMXMapInfo.prototype.initWithXML;
cc.TMXMapInfo.prototype.initWithXML = function (tmxString, tsxMap, textures, textureSizes, imageLayerTextures) {
   
        this._tilesets.length = 0;
        this._layers.length = 0;
        this._imageLayers.length = 0;

        this._tsxMap = tsxMap;
        this._textures = textures;
        this._imageLayerTextures = imageLayerTextures;
        this._textureSizes = textureSizes;

        this._objectGroups.length = 0;
        this._allChildren.length = 0;
        this.properties.length = 0;
        this._tileProperties = {};
        this._tileAnimations = {};
        this._tileObjectGroups = {};

        // tmp vars
        this.currentString = "";
        this.storingCharacters = false;
        this.layerAttrs = cc.TMXLayerInfo.ATTRIB_NONE;
        this.parentElement = cc.TiledMap.NONE;

        return this.parseXMLString(tmxString);
}

cc.TMXMapInfo.prototype.parseXMLString  = function(xmlStr, tilesetFirstGid) {
    let mapXML = this._parser._parseXML(xmlStr);
    let i;

    // PARSE <map>
    let map = mapXML.documentElement;

    let orientationStr = map.getAttribute('orientation');
    let staggerAxisStr = map.getAttribute('staggeraxis');
    let staggerIndexStr = map.getAttribute('staggerindex');
    let hexSideLengthStr = map.getAttribute('hexsidelength');
    let renderorderStr = map.getAttribute('renderorder');
    let version = map.getAttribute('version') || '1.0.0';

    if (map.nodeName === "map") {
        let versionArr = version.split('.');
        let supportVersion = this._supportVersion;
        for (let i = 0; i < supportVersion.length; i++) {
            let v = parseInt(versionArr[i]) || 0;
            let sv = supportVersion[i];
            if (sv < v) {
                cc.logID(7216, version);
                break;
            }
        }   

        if (orientationStr === "orthogonal")
            this.orientation = cc.TiledMap.Orientation.ORTHO;
        else if (orientationStr === "isometric")
            this.orientation = cc.TiledMap.Orientation.ISO;
        else if (orientationStr === "hexagonal")
            this.orientation = cc.TiledMap.Orientation.HEX;
        else if (orientationStr !== null)
            cc.logID(7217, orientationStr);

        if (renderorderStr === 'right-up') {
            this.renderOrder = cc.TiledMap.RenderOrder.RightUp;
        } else if (renderorderStr === 'left-up') {
            this.renderOrder = cc.TiledMap.RenderOrder.LeftUp;
        } else if (renderorderStr === 'left-down') {
            this.renderOrder = cc.TiledMap.RenderOrder.LeftDown;
        } else {
            this.renderOrder = cc.TiledMap.RenderOrder.RightDown;
        }

        if (staggerAxisStr === 'x') {
            this.setStaggerAxis(cc.TiledMap.StaggerAxis.STAGGERAXIS_X);
        }
        else if (staggerAxisStr === 'y') {
            this.setStaggerAxis(cc.TiledMap.StaggerAxis.STAGGERAXIS_Y);
        }

        if (staggerIndexStr === 'odd') {
            this.setStaggerIndex(cc.TiledMap.StaggerIndex.STAGGERINDEX_ODD);
        }
        else if (staggerIndexStr === 'even') {
            this.setStaggerIndex(cc.TiledMap.StaggerIndex.STAGGERINDEX_EVEN);
        }

        if (hexSideLengthStr) {
            this.setHexSideLength(parseFloat(hexSideLengthStr));
        }

        let mapSize = cc.size(0, 0);
        mapSize.width = parseFloat(map.getAttribute('width'));
        mapSize.height = parseFloat(map.getAttribute('height'));
        this.setMapSize(mapSize);

        mapSize = cc.size(0, 0);
        mapSize.width = parseFloat(map.getAttribute('tilewidth'));
        mapSize.height = parseFloat(map.getAttribute('tileheight'));
        this.setTileSize(mapSize);

        // The parent element is the map
        this.properties = getPropertyList(map);
    }

    // PARSE <tileset>
    let tilesets = map.getElementsByTagName('tileset');
    if (map.nodeName !== "map") {
        tilesets = [];
        tilesets.push(map);
    }

    for (i = 0; i < tilesets.length; i++) {
        let selTileset = tilesets[i];
        // If this is an external tileset then start parsing that
        let tsxName = selTileset.getAttribute('source');
        if (tsxName) {
            let currentFirstGID = parseInt(selTileset.getAttribute('firstgid'));
            let tsxXmlString = this._tsxMap[tsxName];
            if (tsxXmlString) {
                this.parseXMLString(tsxXmlString, currentFirstGID);
            }
        } else {
            let images = selTileset.getElementsByTagName('image');
            let multiTextures = images.length > 1;
            let image = images[0];
            let firstImageName = image.getAttribute('source');
            firstImageName = firstImageName.replace(/\\/g, '\/');

            let tiles = selTileset.getElementsByTagName('tile');
            let tileCount = tiles && tiles.length || 1;
            let tile = null;

            let tilesetName = selTileset.getAttribute('name') || "";
            let tilesetSpacing = parseInt(selTileset.getAttribute('spacing')) || 0;
            let tilesetMargin = parseInt(selTileset.getAttribute('margin')) || 0;
            let fgid = parseInt(tilesetFirstGid);
            if (!fgid) {
                fgid = parseInt(selTileset.getAttribute('firstgid')) || 0;
            }

            let tilesetSize = cc.size(0, 0);
            tilesetSize.width = parseFloat(selTileset.getAttribute('tilewidth'));
            tilesetSize.height = parseFloat(selTileset.getAttribute('tileheight'));

            // parse tile offset
            let offset = selTileset.getElementsByTagName('tileoffset')[0];
            let tileOffset = cc.v2(0, 0);
            if (offset) {
                tileOffset.x = parseFloat(offset.getAttribute('x'));
                tileOffset.y = parseFloat(offset.getAttribute('y'));
            }

            let tileset = null;
            for (let tileIdx = 0; tileIdx < tileCount; tileIdx++) {
                if (!tileset || multiTextures) {
                    tileset = new cc.TMXTilesetInfo();
                    tileset.name = tilesetName;
                    tileset.firstGid = fgid;

                    tileset.spacing = tilesetSpacing;
                    tileset.margin = tilesetMargin;
                    tileset._tileSize = tilesetSize;
                    tileset.tileOffset = tileOffset;
                    tileset.sourceImage = this._textures[firstImageName];
                    tileset.imageSize = this._textureSizes[firstImageName] || tileset.imageSize;
                    if (!tileset.sourceImage) {
                        cc.errorID(7221, firstImageName);
                    }
                    this.setTilesets(tileset);
                }

                tile = tiles && tiles[tileIdx];
                if (!tile) continue;

                this.parentGID = parseInt(fgid) + parseInt(tile.getAttribute('id') || 0);
                let tileImages = tile.getElementsByTagName('image');
                if (tileImages && tileImages.length > 0) {
                    image = tileImages[0];
                    let imageName = image.getAttribute('source');
                    imageName = imageName.replace(/\\/g, '\/');
                    tileset.sourceImage = this._textures[imageName];
                    if (!tileset.sourceImage) {
                        cc.errorID(7221, imageName);
                    }
                    
                    let tileSize = cc.size(0, 0);
                    tileSize.width = parseFloat(image.getAttribute('width'));
                    tileSize.height = parseFloat(image.getAttribute('height'));
                    tileset._tileSize = tileSize;
                    tileset.firstGid = this.parentGID;
                }

                this._tileProperties[this.parentGID] = getPropertyList(tile);
                let animations = tile.getElementsByTagName('animation');
                if (animations && animations.length > 0) {
                    let animation = animations[0];
                    let framesData = animation.getElementsByTagName('frame');
                    let animationProp = {frames:[], dt:0, frameIdx:0};
                    this._tileAnimations[this.parentGID] = animationProp;
                    let frames = animationProp.frames;
                    for (let frameIdx = 0; frameIdx < framesData.length; frameIdx++) {
                        let frame = framesData[frameIdx];
                        let tileid = parseInt(fgid) + parseInt(frame.getAttribute('tileid'));
                        let duration = parseFloat(frame.getAttribute('duration'));
                        frames.push({tileid : tileid, duration : duration / 1000, grid: null});
                    }
                }
                let objectgroupXML = tile.getElementsByTagName('objectgroup');
                if(objectgroupXML && objectgroupXML.length > 0){
                    let objectGroup = this._parseObjectGroup(objectgroupXML[0]);
                    this._tileObjectGroups[this.parentGID] = objectGroup;
                }
            }
        }
    }

    // PARSE <layer> & <objectgroup> in order
    let childNodes = map.childNodes;
    for (i = 0; i < childNodes.length; i++) {
        let childNode = childNodes[i];
        if (this._shouldIgnoreNode(childNode)) {
            continue;
        }

        if (childNode.nodeName === 'imagelayer') {
            let imageLayer = this._parseImageLayer(childNode);
            if (imageLayer) {
                this.setImageLayers(imageLayer);
            }
        }

        if (childNode.nodeName === 'layer') {
            let layer = this._parseLayer(childNode);
            this.setLayers(layer);
        }

        if (childNode.nodeName === 'objectgroup') {
            let objectGroup = this._parseObjectGroup(childNode);
            this.setObjectGroups(objectGroup);
        }
    }

    return map;
}

cc.TMXMapInfo.prototype._parseObjectGroup = function(selGroup) {
    let objectGroup = new cc.TMXObjectGroupInfo();
    objectGroup.name = selGroup.getAttribute('name') || '';
    objectGroup.offset = cc.v2(parseFloat(selGroup.getAttribute('offsetx')), parseFloat(selGroup.getAttribute('offsety')));

    let opacity = selGroup.getAttribute('opacity') || 1;
    if (opacity)
        objectGroup._opacity = parseInt(255 * parseFloat(opacity));
    else
        objectGroup._opacity = 255;

    let visible = selGroup.getAttribute('visible');
    if (visible && parseInt(visible) === 0)
        objectGroup.visible = false;

    let color = selGroup.getAttribute('color');
    if (color)
        objectGroup._color.fromHEX(color);

    let draworder = selGroup.getAttribute('draworder');
    if (draworder)
        objectGroup._draworder = draworder;

    // set the properties to the group
    objectGroup.setProperties(getPropertyList(selGroup));

    let objects = selGroup.getElementsByTagName('object');
    if (objects) {
        for (let j = 0; j < objects.length; j++) {
            let selObj = objects[j];
            // The value for "type" was blank or not a valid class name
            // Create an instance of TMXObjectInfo to store the object and its properties
            let objectProp = {};

            // Set the id of the object
            objectProp['id'] = selObj.getAttribute('id') || j;

            // Set the name of the object to the value for "name"
            objectProp["name"] = selObj.getAttribute('name') || "";

            // Assign all the attributes as key/name pairs in the properties dictionary
            objectProp["width"] = parseFloat(selObj.getAttribute('width')) || 0;
            objectProp["height"] = parseFloat(selObj.getAttribute('height')) || 0;

            objectProp["x"] = parseFloat(selObj.getAttribute('x')) || 0;
            objectProp["y"] = parseFloat(selObj.getAttribute('y')) || 0;

            objectProp["rotation"] = parseFloat(selObj.getAttribute('rotation')) || 0;

            objectProp["m_type"] = selObj.getAttribute('type') || "";

            getPropertyList(selObj, objectProp);

            // visible
            let visibleAttr = selObj.getAttribute('visible');
            objectProp['visible'] = !(visibleAttr && parseInt(visibleAttr) === 0);

            // text
            let texts = selObj.getElementsByTagName('text');
            if (texts && texts.length > 0) {
                let text = texts[0];
                objectProp['type'] = cc.TiledMap.TMXObjectType.TEXT;
                objectProp['wrap'] = text.getAttribute('wrap') == '1';
                objectProp['color'] = strToColor(text.getAttribute('color'));
                objectProp['halign'] = strToHAlign(text.getAttribute('halign'));
                objectProp['valign'] = strToVAlign(text.getAttribute('valign'));
                objectProp['pixelsize'] = parseInt(text.getAttribute('pixelsize')) || 16;
                objectProp['text'] = text.childNodes[0].nodeValue;
            }

            // image
            let gid = selObj.getAttribute('gid');
            if (gid) {
                objectProp['gid'] = parseInt(gid);
                objectProp['type'] = cc.TiledMap.TMXObjectType.IMAGE;
            }

            // ellipse
            let ellipse = selObj.getElementsByTagName('ellipse');
            if (ellipse && ellipse.length > 0) {
                objectProp['type'] = cc.TiledMap.TMXObjectType.ELLIPSE;
            }

            //polygon
            let polygonProps = selObj.getElementsByTagName("polygon");
            if (polygonProps && polygonProps.length > 0) {
                objectProp['type'] = cc.TiledMap.TMXObjectType.POLYGON;
                let selPgPointStr = polygonProps[0].getAttribute('points');
                if (selPgPointStr)
                    objectProp["points"] = this._parsePointsString(selPgPointStr);
            }

            //polyline
            let polylineProps = selObj.getElementsByTagName("polyline");
            if (polylineProps && polylineProps.length > 0) {
                objectProp['type'] = cc.TiledMap.TMXObjectType.POLYLINE;
                let selPlPointStr = polylineProps[0].getAttribute('points');
                if(this == undefined || this == null){
                    console.log(`App-> `,this);
                    
                }
                if (selPlPointStr)
                    objectProp["polylinePoints"] = this._parsePointsString(selPlPointStr);
            }

            if (!objectProp['type']) {
                objectProp['type'] = cc.TiledMap.TMXObjectType.RECT;
            }

            // Add the object to the objectGroup
            objectGroup._objects.push(objectProp);
        }

        if (draworder !== 'index') {
            objectGroup._objects.sort(function (a, b) {
                return a.y - b.y;
            });
        }
    }
    return objectGroup;
}

使用: tiledMap.tileObjectGroups[gid] 获取碰撞数据

然后这个扩展 也添加了 获取 对象类型的变量

let objectGroup = tiledMap.getObjectGroup('对象图层')
let point = objectGroup.getObject('出生点');
point.m_type === '标记'

image

2赞

@jare 能不能评估一下, 搬到引擎里去。 这个功能看论坛的记录, 很早就有呼声了

mark一下

3.8依然没有此功能@jare

2024.4.30

4年了还是没有