【问题标题】:Gradually increasing speed of scrolling background in SpriteKit在 SpriteKit 中逐渐提高滚动背景的速度
【发布时间】:2015-05-19 22:05:04
【问题描述】:

我正在使用 SpriteKit 制作一个简单的游戏,并且我有一个滚动背景。简单的情况是在加载游戏场景时将一些背景图像彼此相邻放置,然后当图像滚动出屏幕时水平移动。这是我的游戏场景的didMoveToView 方法的代码。

// self.gameSpeed is 1.0 and gradually increases during the game

let backgroundTexture = SKTexture(imageNamed: "Background")
var moveBackground = SKAction.moveByX(-self.frame.size.width, y: 0, duration: (20 / self.gameSpeed))
var replaceBackground = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
var moveBackgroundForever = SKAction.repeatActionForever(SKAction.sequence([moveBackground, replaceBackground]))

for var i:CGFloat = 0; i < 2; i++ {
    var background = SKSpriteNode(texture: backgroundTexture)
    background.position = CGPoint(x: self.frame.size.width / 2 + self.frame.size.width * i, y: CGRectGetMidY(self.frame))
    background.size = self.frame.size
    background.zPosition = -100
    background.runAction(moveBackgroundForever)

    self.addChild(background)
}

现在我想在游戏的某些点提高滚动背景的速度。可以看到背景水平滚动的持续时间设置为(20 / self.gameSpeed)。显然这是行不通的,因为这段代码只运行一次,因此永远不会更新移动速度来考虑self.gameSpeed 变量的新值。

所以,我的问题很简单:如何根据self.gameSpeed 变量提高背景图像移动的速度(减少持续时间)?

谢谢!

【问题讨论】:

    标签: ios swift sprite-kit


    【解决方案1】:

    您可以使用gameSpeed 变量来设置背景的速度。为此,首先,您需要参考您的两个背景片段(或更多,如果您愿意):

    class GameScene: SKScene {
        lazy var backgroundPieces: [SKSpriteNode] = [SKSpriteNode(imageNamed: "Background"), 
                                                     SKSpriteNode(imageNamed: "Background")]
    
        // ... 
    }
    

    现在你需要你的 gameSpeed 变量:

    var gameSpeed: CGFloat = 0.0 {
        // Using a property observer means you can easily update the speed of the 
        // background just by setting gameSpeed.
        didSet {
            for background in backgroundPieces {
                // Minus, because the background is moving from left to right.
                background.physicsBody!.velocity.dx = -gameSpeed
            }
        }
    }
    

    然后在didMoveToView 中正确定位每一块。此外,要使这种方法起作用,每个背景片段都需要一个物理体,这样您就可以轻松地改变它的速度。

    override func didMoveToView(view: SKView) {
        for (index, background) in enumerate(backgroundPieces) {
            // Setup the position, zPosition, size, etc...
    
            background.physicsBody = SKPhysicsBody(rectangleOfSize: background.size)
            background.physicsBody!.affectedByGravity = false
            background.physicsBody!.linearDamping = 0
            background.physicsBody!.friction = 0
    
            self.addChild(background)
        }
    
        // If you wanted to give the background and initial speed,
        // here's the place to do it.
        gameSpeed = 1.0
    }
    

    您可以在update 中更新gameSpeed,例如使用gameSpeed += 0.5

    最后,在update 中,您需要检查背景片段是否已离开屏幕(左侧)。如果有,则需要将其移至背景片段链的末尾:

    override func update(currentTime: CFTimeInterval) {
        for background in backgroundPieces {
            if background.frame.maxX <= 0 {
                let maxX = maxElement(backgroundPieces.map { $0.frame.maxX })
    
                // I'm assuming the anchor of the background is (0.5, 0.5)
                background.position.x = maxX + background.size.width / 2
            }
        }
    }
    

    【讨论】:

    • 非常感谢您的回答!我试图实现这一点,但我面临一个问题。当gameSpeed 变量改变时,速度设置正确。然而,随着时间的推移,这个速度会逐渐降低,这意味着背景的移动速度会逐渐变慢。每次更新gameSpeed变量时,背景的移动速度都会再次加快,但一段时间后,背景似乎停止了加速。然而,主要问题是背景逐渐移动得更慢。我为此尝试了一些解决方法,但我无法成功
    • 哦,我的错,我忘了包含从物理体中删除 linearDampingfriction 的代码,除非您已经添加了这些代码并且还有其他问题?
    • 太好了,固定速度逐渐降低。现在速度是恒定的,但还有一个问题。背景以初始速度开始移动,几秒钟后,通过更改gameSpeed 变量的值来加速。到目前为止,一切都很好。然后当再次更新变量时会出现问题,此时背景会变慢,即使速度值应该加快它的速度。所以基本上它适用于游戏速度的第一次更新,但之后就不行了。提前谢谢你。
    • 恐怕我没有遇到那个问题...我唯一能想到的可能是问题是您没有增加gameSpeed,而是将其设置为比当前值慢的值?如果不是这样,我们可以在聊天中继续讨论并深入了解:)
    • 很高兴能帮上忙 :) 祝你的项目好运!
    【解决方案2】:

    你可以使用这样的东西

    SKAction.waitforDuration(a certain amount of period to check for the updated values) 
    
    SKAction.repeatActionForever(the action above)
    runAction(your action)
    { // this is the completion block, do whatever you want here, check the values and adjust them accordly
    }
    

    【讨论】:

    • 另外,在 repeatActionForever 块中添加代码来改变等待的值:newWaitValue = functionThatModifiesWait(oldWaitValue) 如果我要对函数进行第一次近似,我会尝试逆椭圆。
    • 我不完全确定你的意思。您的伪代码每 X 秒运行一个代码块。在该代码块中,我需要更新 moveBackground 操作(请参阅问题)以更改速度,对吗?问题不是更新self.gameSpeed 变量,而是将新的游戏速度应用于滚动背景的速度。也许你可以提供更多细节,因为我有点困惑。对不起。
    • 在我提供的伪代码块中,您可以在一定的 X 秒后更新 self.gameSpeed 变量。或者你想在某些特殊事件后提高游戏速度?
    • 我还上传了一个简短的例子,我上次在这里使用过 pastebin.com/NVCzPR1s
    猜你喜欢
    • 1970-01-01
    • 2017-08-29
    • 2017-01-09
    • 1970-01-01
    • 2018-11-06
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多