Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 连接SpriteKit中TileMap上的物理实体_Swift_Sprite Kit_Skphysicsbody_Sktilemapnode - Fatal编程技术网

Swift 连接SpriteKit中TileMap上的物理实体

Swift 连接SpriteKit中TileMap上的物理实体,swift,sprite-kit,skphysicsbody,sktilemapnode,Swift,Sprite Kit,Skphysicsbody,Sktilemapnode,我使用以下函数将PhysicsBody附加到SKTileMapNode的平铺上: static func addPhysicsBody(to tileMap: SKTileMapNode, and tileInfo: String){ let tileSize = tileMap.tileSize let halfWidth = CGFloat(tileMap.numberOfColumns) / 2 * tileSize.width let halfHeight =

我使用以下函数将PhysicsBody附加到SKTileMapNode的平铺上:

 static func addPhysicsBody(to tileMap: SKTileMapNode, and tileInfo: String){

    let tileSize = tileMap.tileSize
    let halfWidth = CGFloat(tileMap.numberOfColumns) / 2 * tileSize.width
    let halfHeight = CGFloat(tileMap.numberOfRows) / 2 * tileSize.height

    for row in 0..<tileMap.numberOfColumns{
        for column in 0..<tileMap.numberOfRows{
            let tileDefinition = tileMap.tileDefinition(atColumn: column, row: row)
            let isCorrectTile = tileDefinition?.userData?[tileInfo] as? Bool
            if isCorrectTile ?? false && tileInfo == "wall"{

                let x = CGFloat(column) * tileSize.width - halfWidth
                let y = CGFloat(row) * tileSize.height - halfHeight

                let tileNode = SKNode()
                tileNode.position = CGPoint(x: x, y: y)
                tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2, y: tileSize.height / 2))
                tileNode.physicsBody!.isDynamic = false
                tileNode.physicsBody!.restitution = 0.0
                tileNode.physicsBody!.categoryBitMask = Constants.PhysicsCategories.wall
                tileNode.physicsBody!.collisionBitMask = Constants.PhysicsCategories.player | Constants.PhysicsCategories.npc | Constants.PhysicsCategories.enemy
                nodesForGraph.append(tileNode)
                tileMap.addChild(tileNode)
            }
        }
    }
}

但是当我这样做的时候,身体完全被搞砸了。

正如奈特弗德拉贡所指出的,没有办法完全按照你的要求去做。不幸的是,SpriteKit中的平铺贴图还有很多需要改进的地方。但是你可以尝试这种技术来减少物理体的数量

想法#1-手动绘制物理实体 在编辑器中创建平铺贴图。只需在地图上绘制瓷砖纹理;不要给他们分配任何物理实体。然后继续在编辑器中工作,将颜色精灵(
SKSpriteNodes
)拖动到需要物理实体的地图部分。对节点进行造型,使需要物理实体的区域成为可能的最大矩形。这最适用于大型平面,如墙、地板、天花板、平台、板条箱等。这很乏味,但与像现在这样自动将实体指定给所有瓷砖相比,模拟中的物理实体要少得多

想法#2-不使用物理实体 这个想法可能需要更多的工作,但是你可以避免使用物理实体。首先,在编辑器中创建平铺贴图。分析你的地图,以确定哪些瓷砖标记了一个障碍,玩家不应越过该障碍。为该类型的磁贴分配用户数据标识符。对于不同类型的屏障,您需要不同类别的标识符,并且您可能还需要设计适合这种方法的艺术品

一旦您的屏障磁贴被充分识别,编写代码检查玩家精灵当前占用的磁贴的用户数据值,并相应地限制精灵的移动。例如,如果玩家输入一个标记上边界的标题,你的移动代码将不允许玩家精灵向上移动。同样,如果玩家输入一个标记最左边边界的平铺,你的移动代码将不允许玩家向左移动


你可以看看我在哪里提出了基本相同的想法。不幸的是,SpriteKit的平铺贴图无法完美解决此问题。

正如Knight0fDragon所指出的,没有办法完全按照您的要求执行。不幸的是,SpriteKit中的平铺贴图还有很多需要改进的地方。但是你可以尝试这种技术来减少物理体的数量

想法#1-手动绘制物理实体 在编辑器中创建平铺贴图。只需在地图上绘制瓷砖纹理;不要给他们分配任何物理实体。然后继续在编辑器中工作,将颜色精灵(
SKSpriteNodes
)拖动到需要物理实体的地图部分。对节点进行造型,使需要物理实体的区域成为可能的最大矩形。这最适用于大型平面,如墙、地板、天花板、平台、板条箱等。这很乏味,但与像现在这样自动将实体指定给所有瓷砖相比,模拟中的物理实体要少得多

想法#2-不使用物理实体 这个想法可能需要更多的工作,但是你可以避免使用物理实体。首先,在编辑器中创建平铺贴图。分析你的地图,以确定哪些瓷砖标记了一个障碍,玩家不应越过该障碍。为该类型的磁贴分配用户数据标识符。对于不同类型的屏障,您需要不同类别的标识符,并且您可能还需要设计适合这种方法的艺术品

一旦您的屏障磁贴被充分识别,编写代码检查玩家精灵当前占用的磁贴的用户数据值,并相应地限制精灵的移动。例如,如果玩家输入一个标记上边界的标题,你的移动代码将不允许玩家精灵向上移动。同样,如果玩家输入一个标记最左边边界的平铺,你的移动代码将不允许玩家向左移动


你可以看看我在哪里提出了基本相同的想法。不幸的是,SpriteKit的瓷砖贴图没有完美的解决方案。

我建议应用线条扫描算法将瓷砖合并在一起

您可以通过四个步骤来完成此操作

  • 在SKTileMap中迭代瓷砖的位置

  • 查找彼此相邻的瓷砖

  • 对于每组相邻瓷砖,收集:

    • 左下角坐标
    • 右上角坐标
  • 绘制一个正方形,然后移动到下一组瓷砖,直到瓷砖坐标用完为止


  • 第一步:创建包含所有位置节点的数组

    func tilephysics() {
    
        let tilesize = tileMap.tileSize
        let halfwidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tilesize.width
        let halfheight =  CGFloat(tileMap.numberOfRows) / 2.0 * tilesize.height
    
        for col in 0 ..< tileMap.numberOfColumns {
    
            for row in 0 ..< tileMap.numberOfRows {
    
                if (tileMap.tileDefinition(atColumn: col, row: row)?.userData?.value(forKey: "ground") != nil) {
    
                    let tileDef = tileMap.tileDefinition(atColumn: col, row: row)!
                    let tile = SKSpriteNode()
    
                    let x = round(CGFloat(col) * tilesize.width - halfwidth + (tilesize.width / 2))
                    let y = round(CGFloat(row) * tilesize.height - halfheight + (tilesize.height / 2))
    
                    tile.position = CGPoint(x: x, y: y)
                    tile.size = CGSize(width: tileDef.size.width, height: tileDef.size.height)
    
                    tileArray.append(tile)
                    tilePositionArray.append(tile.position)
                }
            }
        }
        algorithm()
    }
    

    正确地应用这些步骤,您应该会看到您的平铺以大正方形合并在一起;像这样:

    解决这个问题我很开心。如果我帮助过你,请告诉我。
    我最近才开始编码,正在寻找新的挑战。如果您有挑战或项目我可能会有所贡献,请联系我。

    我建议应用线条扫描算法将瓷砖合并在一起

    您可以通过四个步骤来完成此操作

  • 在SKTileMap中迭代瓷砖的位置

  • 查找彼此相邻的瓷砖

  • 对于每组相邻瓷砖,收集:

    • 左下角坐标
    • 右上角坐标
  • 绘制一个正方形,然后移动到下一组瓷砖,直到瓷砖坐标用完为止


  • 第一步:创建包含所有位置节点的数组

    func tilephysics() {
    
        let tilesize = tileMap.tileSize
        let halfwidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tilesize.width
        let halfheight =  CGFloat(tileMap.numberOfRows) / 2.0 * tilesize.height
    
        for col in 0 ..< tileMap.numberOfColumns {
    
            for row in 0 ..< tileMap.numberOfRows {
    
                if (tileMap.tileDefinition(atColumn: col, row: row)?.userData?.value(forKey: "ground") != nil) {
    
                    let tileDef = tileMap.tileDefinition(atColumn: col, row: row)!
                    let tile = SKSpriteNode()
    
                    let x = round(CGFloat(col) * tilesize.width - halfwidth + (tilesize.width / 2))
                    let y = round(CGFloat(row) * tilesize.height - halfheight + (tilesize.height / 2))
    
                    tile.position = CGPoint(x: x, y: y)
                    tile.size = CGSize(width: tileDef.size.width, height: tileDef.size.height)
    
                    tileArray.append(tile)
                    tilePositionArray.append(tile.position)
                }
            }
        }
        algorithm()
    }
    

    正确地应用这些步骤,您应该会看到您的平铺以大正方形合并在一起;像这样:

    var dir = [String]()
    var pLoc = [CGPoint]()
    var adT = [CGPoint]()
    
    func algorithm(){
    
        let width = tileMap.tileSize.width
        let height = tileMap.tileSize.height
        let rWidth = 0.5 * width
        let rHeight = 0.5 * height
    
        var ti:Int = 0
        var ti2:Int = 0
        var id:Int = 0
        var dl:CGPoint = CGPoint(x: 0, y: 0)
    
        var tLE = [CGPoint]()
        var tRE = [CGPoint]()
    
        for t in tilePositionArray {
    
            if (ti-1 < 0) || (tilePositionArray[ti-1].y != tilePositionArray[ti].y - height) {
    
                dl = CGPoint(x: t.x - rWidth, y: t.y - rHeight)
    
            }
    
            if (ti+1 > tilePositionArray.count-1) {
                tLE.append(dl)
    
                tRE.append(CGPoint(x: t.x + rWidth, y: t.y + rHeight))
    
            } else if (tilePositionArray[ti+1].y != tilePositionArray[ti].y + height) {
    
                if let _ = tRE.first(where: {
    
                    if $0 == CGPoint(x: t.x + rWidth - width, y: t.y + rHeight) {id = tRE.index(of: $0)!}
    
                    return $0 == CGPoint(x: t.x + rWidth - width, y: t.y + rHeight)}) {
    
                    if tLE[id].y == dl.y {
    
                        tRE[id] = CGPoint(x: t.x + rWidth, y: t.y + rHeight)
    
                    } else {
    
                        tLE.append(dl)
    
                        tRE.append(CGPoint(x: t.x + rWidth, y: t.y + rHeight))
    
                    }
    
                } else {
    
                    tLE.append(dl)
    
                    tRE.append(CGPoint(x: t.x + rWidth, y: t.y + rHeight))
    
                }
    
            }
    
            ti+=1
    
        }
    
    for t in tLE {
    
            let size = CGSize(width: abs(t.x - tRE[ti2].x), height: abs(t.y - tRE[ti2].y))
            let loadnode = SKNode()
    
            loadnode.physicsBody = SKPhysicsBody(rectangleOf: size)
            loadnode.physicsBody?.isDynamic = false
            loadnode.physicsBody?.affectedByGravity = false
            loadnode.physicsBody?.restitution = 0
    
            loadnode.physicsBody?.categoryBitMask = 2
    
            loadnode.position.x = t.x + size.width / 2
            loadnode.position.y = t.y + size.height / 2
    
            scene.addChild(loadnode)
    
            ti2 += 1
    
        }
    }