我的 SKSpriteNode 速度值未正确更新

Posted

技术标签:

【中文标题】我的 SKSpriteNode 速度值未正确更新【英文标题】:My SKSpriteNode speed values are not updating properly 【发布时间】:2020-10-19 22:46:19 【问题描述】:

我想要做的是更新我的 SKSpriteNodes,这样我就可以动态地改变它们的滚动速度,但是它们并不能真正持续地工作。我没有包含代码,但是我有另一种带有开关盒的方法,该方法在状态更改时设置platformSpeed 的值(在这种情况下,开关盒使用 UIButtons 更改)。在我的代码中,我有一个 SKSpriteNode 数组和一个包含 didSetplatformSpeed 属性,因此我的值已正确更新。

在创建平台的方法中,我将 SpriteNode 分组到 platformGroup 中,然后使用 addChild() 循环遍历它们。不知道它为什么会这样,但这里有一个快速视频,展示了它的实际效果:

demonstration clip

因此,我正在使用按钮更改开关盒,如您所见,并非所有节点的速度都在正确更新,有些节点比其他节点更快并最终通过它们。我需要他们彼此保持相等的距离。

现在这是我的代码:

class GameScene: SKScene, SKPhysicsContactDelegate 

var platformGroup = [SKSpriteNode]()
var platformSpeed: CGFloat = 1.0 
    didSet 
        for platforms in platformGroup 
            platforms.speed = platformSpeed 
        
    


let platformTexture = SKTexture(imageNamed: "platform")
var platformPhysics: SKPhysicsBody!


func createPlatforms() 
    
    let platformLeft = SKSpriteNode(texture: platformTexture)
    platformLeft.physicsBody = platformPhysics.copy() as? SKPhysicsBody
    platformLeft.physicsBody?.isDynamic = false
    platformLeft.scale(to: CGSize(width: platformLeft.size.width * 4, height: platformLeft.size.height * 4))
    platformLeft.zPosition = 20

    let platformRight = SKSpriteNode(texture: platformTexture)
    platformRight.physicsBody = platformPhysics.copy() as? SKPhysicsBody
    platformRight.physicsBody?.isDynamic = false
    platformRight.scale(to: CGSize(width: platformRight.size.width * 4, height: platformRight.size.height * 4))
    platformRight.zPosition = 20
    
    let scoreNode = SKSpriteNode(color: UIColor.clear, size: CGSize(width: frame.width, height: 32))
    scoreNode.physicsBody = SKPhysicsBody(rectangleOf: scoreNode.size)
    scoreNode.physicsBody?.isDynamic = false
    scoreNode.name = "scoreDetect"
    scoreNode.zPosition = 40

    platformGroup = [platformLeft, platformRight, scoreNode]

    let yPosition = frame.width - platformRight.frame.width

    let max = CGFloat(frame.width / 4)
    let xPosition = CGFloat.random(in: -80...max)

    let gapSize: CGFloat = -50


    platformLeft.position = CGPoint(x: xPosition + platformLeft.size.width - gapSize, y: -yPosition)
    platformRight.position = CGPoint(x: xPosition + gapSize, y: -yPosition)
    scoreNode.position = CGPoint(x: frame.midX, y: yPosition - (scoreNode.size.width / 1.5))

    let endPosition = frame.maxY + (platformLeft.frame.height * 3)

    let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
    let moveSequence = SKAction.sequence([moveAction, SKAction.removeFromParent()])
    
    for platforms in platformGroup 
        addChild(platforms)
        platforms.run(moveSequence)
    
    
    platformCount += 1


func loopPlatforms() 
    let create = SKAction.run  [unowned self] in
        self.createPlatforms()
        platformCount += 1
    
    
    let wait = SKAction.wait(forDuration: 1.1)
    let sequence = SKAction.sequence([create, wait])
    let repeatForever = SKAction.repeatForever(sequence)
    
    run(repeatForever)

【问题讨论】:

【参考方案1】:

我想我知道出了什么问题。当您更改platformSpeed 时,它会更改platformGroup 中所有平台的速度。并且createPlatforms() 被多次调用。现在,每次调用它时,您都会创建一对平台并将它们分配给platformGroup。由于您多次调用该函数,它会覆盖数组中的任何现有值。这就是为什么更改 platformSpeed 只会更新您创建的最新平台的速度——旧平台保持相同的速度,因为它们不再在 platformGroup 中。

要解决此问题,我的建议是让 platformGroup 存储当前屏幕上的所有平台。你可以通过改变来做到这一点

    platformGroup = [platformLeft, platformRight, scoreNode]

类似

    let newNodes = [platformLeft, platformRight, scoreNode]
    platformGroup += newNodes
    // Alternatively, platformGroup.append(contentsOf: newNodes)

现在您需要确保 1) 仅将新节点添加到场景中,以及 2) 从父节点中删除旧节点时从 platformGroup 中删除它们。你可以通过改变来做到这一点

    let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
    let moveSequence = SKAction.sequence([moveAction, SKAction.removeFromParent()])
    
    for platforms in platformGroup 
        addChild(platforms)
        platforms.run(moveSequence)
    

类似

    let moveAction = SKAction.moveBy(x: 0, y: endPosition, duration: 7)
    
    for node in newNodes 
        let moveSequence = SKAction.sequence([
            moveAction, 
            SKAction.removeFromParent(),
            SKAction.run 
                self.platformGroup.remove(node)
            
        ])

        addChild(node)
        node.run(moveSequence)
    

既然您正在跟踪所有平台,那么您的速度更改应该一致地应用于屏幕上的每个平台。希望这行得通!

【讨论】:

以上是关于我的 SKSpriteNode 速度值未正确更新的主要内容,如果未能解决你的问题,请参考以下文章

如何找到 SKSpriteNode 的速度作为 x 和 y 值?

需要帮助更改在 didMoveToView 中调用的 SKSpriteNode 的速度、方向和生成时间

Flutter/Dart - 文本值未正确显示

阻止 SKSpriteNode 减速

BindingBeans中的复合值未更新

颤振列表值未更新