swift - 创建无图像的无尽背景

标签 swift sprite-kit

我正在使用 SwiftSpriteKit 创建一个简单的游戏。 我想添加一个无尽的背景(垂直),我只找到了带图像背景的答案,但我需要在没有图像的情况下做到这一点,只有背景颜色。 我考虑过检查播放器是否在 frame.maxY 中,如果是,则将其移回起点,但我想知道是否有更好的主意。

//Does not matter which ring we chose as all ring's 'y' position is the same.
func moveBackgroundUp(){
    if ((mPlayer.position.y >= self.frame.maxY) || (mRingOne.position.y >= self.frame.maxY)) {
        mPlayer.position.y = 150 //mPlayers original starting point.
        for ring in mRings {
            ring.position.y = 350
        }
    }
}

提前致谢!

最佳答案

不要只是将背景移到屏幕上,这真的不是解决问题的方法。你应该做的是检测相机的位置(假设它随玩家移动),当它的位置即将占据你当前背景 Sprite 占用空间之外的空间时,添加一个新的背景 Sprite 到场景中最后一个离开了。以下是如何仅使用红色 Sprite 执行此操作的示例:

首先在场景中添加一个属性来跟踪关卡位置:

// To track the y-position of the level
var levelPositionY: CGFloat = 0.0

现在创建一个方法来更新你的背景:

func updateBackground() {
    let cameraPos = camera!.position
    if cameraPos.y > levelPositionY - (size.height * 0.55) {
        createBackground()
    }
}

func createBackground() {

    // Create a new sprite the size of your scene
    let backgroundSprite = SKSpriteNode(color: .red, size: size)
    backgroundSprite.anchorPoint = CGPoint(x: 0.5, y: 0)
    backgroundSprite.position = CGPoint(x: 0, y: levelPositionY)

    // Replace backgroundNode with the name of your backgroundNode to add the sprite to
    backgroundNode.addChild(backgroundSprite)
    levelPositionY += backgroundSprite.size.height
}

现在您想在重写的 update(_:) 方法中调用 updateBackground:

override func update(_ currentTime: TimeInterval) {

    // All your other update code
    updateBackground()

}

此外,请确保在首次创建场景时创建初始背景:

override func didMove(to view: SKView) {
    createBackground()
}

注意! - 为背景 Sprite 设置自定义 anchor 很重要,此代码才能正常工作。 (0.5, 0) 的 anchor 允许背景 Sprite 在 x 轴上锚定在场景的中间,但在 y 轴上锚定在场景的底部。这使您可以轻松地将一个堆叠在另一个之上。

编辑 - 我忘了提一下,保存资源并移除可见区域之外且不会返回的任何背景节点也是一个好主意(即连续滚动游戏你不能倒退的地方)。您可以通过更新上面的 updateBackground 方法来做到这一点:

func updateBackground() {
    let cameraPos = camera!.position
    if cameraPos.y > levelPositionY - (size.height * 0.55) {
        createBackground()
    }

    // Make sure to change 'backgroundNode' to whatever the name of your backgroundNode is.
    for bgChild in backgroundNode.children {
        // This will convert the node's coordinates to scene's coordinates. See below for this function
        let nodePos = fgNode.convert(fgChild.position, to: self)
        if !isNodeVisible(bgChild, positionY: nodePos.y) {
            // Remove from it's parent node
            bgChild.removeFromParent()
        }
    }
}

func isNodeVisible(_ node: SKNode, positionY: CGFloat) -> Bool {
    if !camera!.contains(node) {
        if positionY < camera!.position.y - size.height * 2.0 {
            return false
        }
    }
    return true
}

所以在上面你只是循环遍历背景节点中的所有子节点并检测它们是否不在 View 中,如果是,则将它们从父节点中移除。确保将我的通用 backgroundNode 更改为您的后台节点的任何名称。

关于swift - 创建无图像的无尽背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41652060/

相关文章:

ios - SpriteKit 展开可选错误(Swift)

swift - 是否可以有多个参数选择?

ios - SpriteKit SKScene 中的相机属性始终为 nil

ios - 使用 scaleMode .AspectFit 时如何更改 SKView 信箱颜色

ios - 根据用户点击屏幕的位置调用不同的功能

sprite-kit - Sprite Kit 不再使用 iOS10 播放声音

ios - 如何让SKSpriteNode重新出现在它的SKScene的对面?

ios - 如何将数据从 subview Controller 传递到父 View Controller ? swift

swift - 如何在 Swift 中延迟 For 循环直到声音播放完毕

ios - RxSwift 中 UITapGestureRecognizer 无法识别的选择器