从 SKTileMapNode 中删除特定的瓦片

Posted

技术标签:

【中文标题】从 SKTileMapNode 中删除特定的瓦片【英文标题】:Removing a Particular Tile from SKTileMapNode 【发布时间】:2017-04-21 11:45:05 【问题描述】:

我有一个 Tile Map Node,它涵盖了我的整个游戏场景 (GameScene.sks)。屏幕顶部有一个敌人。还有一些小房子布置在底部。只有这些房屋来自瓦片地图节点。敌人应该向这些房屋中的任何一个开枪。 contactBitMask 设置为射击和房屋瓷砖。我想用contactBitMask 移除被子弹击中的房子。无论如何,我有以下几行代码。

class GameScene: SKScene, SKPhysicsContactDelegate 

    var destructibleCount = Int() // destructibleCount
    func setupDestructiblePhysics() 
        guard let obstaclesTileMap = obstaclesTileMap else  return 
        for row in 0..<obstaclesTileMap.numberOfRows 
            for column in 0..<obstaclesTileMap.numberOfColumns 
                guard let tile = tile(in: obstaclesTileMap, at: (column, row)) // a function returning SKTileDefinition
                    else  continue 
                guard tile.userData?.object(forKey: "destructible") != nil // 'destructible' is set through TileSet
                    else  continue 
                let node = SKNode()
                node.physicsBody = SKPhysicsBody(rectangleOf: tile.size)
                node.physicsBody?.isDynamic = false
                node.physicsBody?.categoryBitMask = PhysicsCategory.Building
                node.position = obstaclesTileMap.centerOfTile(atColumn: column, row: row)
                node.name = "building"
                obstaclesTileMap.addChild(node)
                destructibleCount += 1
            
        
    

    func didBegin(_ contact: SKPhysicsContact) 
        let enemyBeamContact = contact.bodyA.categoryBitMask == PhysicsCategory.EnemyShot ? contact.bodyB : contact.bodyA
        switch enemyBeamContact.categoryBitMask 
        case PhysicsCategory.Building:
            if let nodeA = contact.bodyA.node 
                let column = obstaclesTileMap!.tileColumnIndex(fromPosition: nodeA.position)
                let row = obstaclesTileMap!.tileRowIndex(fromPosition: nodeA.position)
                print(column, row)
                enumerateChildNodes(withName: "building", using:  node, _ in
                    if node.position == nodeA.position 
                        node.removeFromParent()
                    
                )

                if let tile = tile(in: obstaclesTileMap!, at: (column, row)) 
                    // not being used
                
            
            if let nodeB = contact.bodyB.node 
                // bullet //
                if nodeB.name == "beam" 
                    nodeB.removeFromParent()
                
            
        default:
            break
        
    

当子弹击中房屋时,didBegin 物理方法会告诉我被击中的瓷砖。 (见打印(列,行))。我遇到的困难是如何移除被击中的瓷砖。 node.removeFromParent() 无效。而且我无法移除任何瓷砖。我有一种感觉,你无法移除一块瓷砖。或者我们可以吗?我认为使用瓷砖是开发 SpriteKit 游戏的一种有效方式。但在我看来并非如此。我想我可以以编程方式将这些房屋添加到场景中。谢谢。

【问题讨论】:

根据定义,SkTileMapNode 对象是一个整体的节点?我猜你不能删除特定的图块。 试试SubclassingSKTileDefinition。您可以创建类的自定义生命周期。 嗯...感谢您的建议。我想我只是将它们作为 SKTexture 添加到场景中。 【参考方案1】:

SKTilemapNode 本身就是一个整体,因此接触测试只会告诉您何时接触到瓦片地图,而不是单个瓦片。

您可以做的是使用瓷砖地图来设计关卡,但在didMove(to:) 函数中,您可以浏览瓷砖地图并为您找到的每个房屋创建单独的SKSpriteNode。您可以使用SKTilemapNode 的函数来获取您需要的信息(您使用的纹理、位置等):

tileDefinition(atColumn:row:) tileGroup(atColumn:row:) centerOfTile(atColumn:row:)

一旦您完成了瓷砖地图的行走并创建了所有房屋,请从场景中移除瓷砖地图并像往常一样与房屋接触。

希望对你有帮助!

【讨论】:

以上是关于从 SKTileMapNode 中删除特定的瓦片的主要内容,如果未能解决你的问题,请参考以下文章

更改 SKTileMapNode 中特定图块的颜色

将 SKSpriteNode 移动到 SKTileMapNode 上的特定图块

Spritekit Hexagonal map:SKAction 中的瓦片检测。

Sktilemapnode 从一张图片加载图块

列和行索引高于 SKTileMapNode 中的列和行数

真实设备上的 SKTileMap 物理错误