当我只创建一个时,为什么会有多个 SKSpriteNode 和 SKAudioNode 对象?

丹尼尔·布劳尔

我创建了一个 SKSpriteNode 对象,但创建了多个对象,显示为它们的字符串。来自 SKAudioNode 对象的声音也被多次复制以产生混响效果。

这是下面的代码。当我在 didBegin 回调方法中添加将 PhysicsBody 对象的固定属性设置为 true 的代码时,我注意到它这样做了。

这是一个屏幕截图。注意有多个爆炸 SKSpriteNode 对象。我只为爆炸创建了一个 SKSpriteNode 对象。

多辆汽车爆炸

我怀疑某处有一个设置可以更改以禁用此效果。

import UIKit
import SpriteKit

class GameScene: SKScene {

    let player = SKSpriteNode(imageNamed: "player")
    var moveRate: CGFloat!

    override func didMove(to view: SKView) {

        physicsWorld.contactDelegate = self

        if UIDevice.current.userInterfaceIdiom == .phone {
            moveRate = 5
        } else {
            moveRate = 15
        }

        player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
        player.physicsBody?.isDynamic = true
        player.physicsBody?.affectedByGravity = false
        player.physicsBody?.categoryBitMask = 0b00001
//        player.physicsBody?.collisionBitMask = 0b00001
        player.physicsBody?.contactTestBitMask = 0b00001

        player.position = CGPoint(x: 20 + player.size.width/2, y: view.frame.height / 2)

        addChild(player)

        let carEngineStart = SKAudioNode(fileNamed: "car_engine_running")

        addChild(carEngineStart)

        run(SKAction.repeatForever(
            SKAction.sequence([
                SKAction.run(addCompetitor),
                SKAction.wait(forDuration: 4)
                ])
        ))

    }

    override func update(_ currentTime: TimeInterval) {

        let internalRollSign = TrialSpriteKit.sign(internalRoll)

        switch internalRollSign {
        case .zero:
            break
        case .positive:
            if player.position.y < self.size.height {
                player.position.y += moveRate
            }
        case .negative:
            if player.position.y > 0 {
                player.position.y -= moveRate
            }
        }

    }

    enum Car: String, CaseIterable {

        case blue = "blue"
        case green = "green"
        case orange = "orange"
        case purple = "purple"
        case utili = "utili"
        case white = "white"
        case yellow = "yellow"

        static func random<G: RandomNumberGenerator>(using generator: inout G) -> Car {
            return Car.allCases.randomElement(using: &generator)!
        }

        static func random() -> Car {
            var g = SystemRandomNumberGenerator()
            return Car.random(using: &g)
        }

    }

    func random() -> CGFloat {
        return CGFloat(Float(arc4random()) / /* 0xFFFFFFFF */ 4294967296)
    }

    func random(min: CGFloat, max: CGFloat) -> CGFloat {
        return random() * (max - min) + min
    }

    func addCompetitor() {

        // Create sprite
        let carString = Car.random().rawValue
        let car = SKSpriteNode(imageNamed: carString)

        car.physicsBody = SKPhysicsBody(rectangleOf: car.size) // 1
        car.physicsBody?.isDynamic = true
        car.physicsBody?.affectedByGravity = false
//        car.physicsBody?.categoryBitMask = 0b00001
        car.physicsBody?.collisionBitMask = 0b00001
        car.physicsBody?.contactTestBitMask = 0b00001

        // Determine where to spawn the car along the Y axis
        let actualY = random(min: car.size.height/2, max: size.height - car.size.height/2)

        // Position the car slightly off-screen along the right edge,
        // and along a random position along the Y axis as calculated above
        car.position = CGPoint(x: size.width + car.size.width/2, y: actualY)

        // Add the car to the scene
        addChild(car)

        // Determine speed of the car
        let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))

        // Create the actions
        let actionMove = SKAction.move(to: CGPoint(x: -car.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
        let actionMoveDone = SKAction.removeFromParent()
        car.run(SKAction.sequence([actionMove, actionMoveDone]))

    }

}

extension GameScene: SKPhysicsContactDelegate {

    func didBegin(_ contact: SKPhysicsContact) {

        contact.bodyA.pinned = true
        player.physicsBody?.pinned = true

        let explosion = SKSpriteNode(imageNamed: "explosion")

        explosion.position = contact.contactPoint

        addChild(explosion)

        run(
            SKAction.sequence(
                [
                    SKAction.playSoundFileNamed("car_explosion", waitForCompletion: true),
                    SKAction.run({
                        explosion.removeFromParent()
                        contact.bodyB.node?.removeFromParent()
                    }),
                    SKAction.wait(forDuration: 1),
                    SKAction.run({
                        self.player.zRotation = 0
                        self.player.position = CGPoint(x: 20 + self.player.size.width/2, y: self.view!.frame.height / 2)
                        self.player.physicsBody?.pinned = false
                    })
                ]
            )
        )

     }

}
马克·西姆奇克

You have the reason for the multiple nodes in your question.

I noticed it doing this when I added the code to set the pinned properties of the physicsBody objects to true in the didBegin callback method.

According to the SpriteKit documentation, when you set the pinned property to true and the parent node has a physics body, the two bodies are treated as if they are connected with a pin joint.

Because the two bodies are connected, contact is being made repeatedly, even if there isn't a collision, resulting in repeated calls to the didBegin function. Each call to didBegin creates a new sprite node. Your game is calling didBegin many more times than you expect so you end up with more sprite nodes than you expect.

一般的解决方案是只有在发生碰撞时才创建爆炸精灵节点,并且每次碰撞只创建一次精灵节点。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用JSON对象创建表格,为什么最后一行的第一行有两行和一个空行的“ td”

当我选择一个对象字段时,为什么lodash的_.unique不返回唯一对象?

调整大小和缩放SKSpriteNode

SKAudioNode播放声音一次

无法创建SKSpriteNode的子类

如何创建SKSpriteNode的图像?

创建对象和对象长度

我已经用TextView和ImageView创建了一个Place对象,但是当我尝试添加一个place对象时出现此错误

我已经重载<<和=运算符。为什么当我将一个对象分配给另一个对象并尝试打印该对象时,却打印出了垃圾邮件?

为什么当我尝试从父类创建子类(向下转换)时,得到一个空对象

为什么我的SKAudioNode给我一个错误?

带有SKSpriteNode和纹理图集的SpriteKit绘制数量很高

当我仅使用Unity时,为什么会有海豚和Konqueror的更新?

困惑:SKSpriteNode和SKTexture的区别。

可以按名称搜索SKSpriteNode对象吗

从子级SKSpriteNode向SKScene添加一个SKSpriteNode

如何从点击获取SKSpriteNode子类化对象

在Swift中使用SKSpriteNode和SKAction创建具有随机Y坐标的视差云

用SkSpriteNode旋转对象

为什么当我们只给一个变量赋一个变量并打印时打印所有对象的属性

分配在SKAudioNode上运行play()时返回的SKAction?

初始化SKSpriteNode对象时,nil异常

Swift 3.0:当给非SKView父对象时,SKSpriteNode作为Button不起作用?

使用静态方法和属性创建 SKSpriteNode

当我尝试发出帖子请求时,它只返回创建日期和对象 ID

当我创建一个函数时,对象中的 (function(){}()) 是什么

当我创建一个对象并使用 getter 和 setter 获取该整数值时,为什么整数为 0?

在 Foundry Scenarios 中,当一个场景被一个对象保存和支持时,删除按钮有什么作用?

为什么一个 API 响应只返回一个对象和一组对象?