如何在 spriteKit swift 4 中制作无限背景

Posted

技术标签:

【中文标题】如何在 spriteKit swift 4 中制作无限背景【英文标题】:how to make infinite background in spriteKit swift 4 【发布时间】:2018-03-26 20:50:44 【问题描述】:

我尝试通过节点制作一个无限的背景,但是背景没有变成无限并且被打断,第三个背景还没有显示出来。第一次演出后,场景中的节点数越来越多,如何解决?

import SpriteKit
import GameplayKit

class GameScene: SKScene 


   var bgNode: SKNode!
   var overlay: SKNode!
   var overlayWidth: CGFloat!
   //var viewSize: CGSize!
   var levelPositionX: CGFloat = 0.0
   //var speed: CGFloat = 5.5


   override func didMove(to view: SKView) 
    setupNode()
    //viewSize = CGSize(width: frame.size.width, height: 
                                                     
                                              frame.size.height )
    
  

  func setupNode() 
    let worldNode = childNode(withName: "World")!
    bgNode = worldNode.childNode(withName: "Background")!
    overlay = bgNode.childNode(withName: "Overlay")!.copy() as! 
  SKNode
    overlayWidth = overlay.calculateAccumulatedFrame().width
  

   func createBackgroundOverlay() 
    let backgroundOverlay = overlay.copy() as! SKNode
    backgroundOverlay.position = CGPoint(x: 0.0, y: 0.0)
    
    bgNode.addChild(backgroundOverlay)
    levelPositionX += overlayWidth


func update() 
    bgNode.position.x -= 5
    if bgNode.position.x <= -self.frame.size.width 
         bgNode.position.x = self.frame.size.width * 2
        createBackgroundOverlay()
        
      
  

  override func update(_ currentTime: TimeInterval) 
      update()
      

【问题讨论】:

【参考方案1】:

在我的无尽奔跑游戏中,我实现了与您的应用非常相似的无尽背景和地面(或地板)。下面我将讨论我在游戏中使用的步骤。

第 1 步:在您的 GameScene.swift 文件中添加这些变量。

var backgroundSpeed: CGFloat = 80.0 // speed may vary as you like
var deltaTime: TimeInterval = 0
var lastUpdateTimeInterval: TimeInterval = 0

第二步:在GameScene文件中,制作setUpBackgrouds方法如下

func setUpBackgrounds() 
    //add background

    for i in 0..<3 
        // add backgrounds, my images were namely, bg-0.png, bg-1.png, bg-2.png

        let background = SKSpriteNode(imageNamed: "bg-\(i).png")
        background.anchorPoint = CGPoint.zero
        background.position = CGPoint(x: CGFloat(i) * size.width, y: 0.0)
        background.size = self.size
        background.zPosition = -5
        background.name = "Background"
        self.addChild(background)

    

    for i in 0..<3 
        // I have used one ground image, you can use 3
        let ground = SKSpriteNode(imageNamed: "Screen.png")
        ground.anchorPoint = CGPoint(x: 0, y: 0)
        ground.size = CGSize(width: self.size.width, height: ground.size.height)
        ground.position = CGPoint(x: CGFloat(i) * size.width, y: 0)
        ground.zPosition = 1
        ground.name = "ground"
        self.addChild(ground)

    

第 3 步:现在我们必须从更新方法中捕获 timeIntervals

override func update(_ currentTime: TimeInterval) 
    if lastUpdateTimeInterval == 0 
        lastUpdateTimeInterval = currentTime
    

    deltaTime = currentTime - lastUpdateTimeInterval
    lastUpdateTimeInterval = currentTime

第 4 步:这是最重要的部分,通过枚举子节点来移动我们的背景和 groungFloor。在 GameScene.swift 文件中添加这两个方法。

func updateBackground() 
    self.enumerateChildNodes(withName: "Background")  (node, stop) in

        if let back = node as? SKSpriteNode 
            let move = CGPoint(x: -self.backgroundSpeed * CGFloat(self.deltaTime), y: 0)
            back.position += move

            if back.position.x < -back.size.width 
                back.position += CGPoint(x: back.size.width * CGFloat(3), y: 0)
            
        

    


func updateGroundMovement() 
    self.enumerateChildNodes(withName: "ground")  (node, stop) in

        if let back = node as? SKSpriteNode 
            let move = CGPoint(x: -self.backgroundSpeed * CGFloat(self.deltaTime), y: 0)
            back.position += move

            if back.position.x < -back.size.width 
                back.position += CGPoint(x: back.size.width * CGFloat(3), y: 0)
            
        

    

第 5 步: 此时您应该会在 updateBackground 和 updateGroundMovement 方法中收到此错误:“Binary operator '+=' cannot be applied to two 'CGPoint'operands”。

现在我们需要实现运算符重载来解决这个问题。创建一个新的 Swift 文件并将其命名为 Extensions.swift ,然后实现如下:

//  Extensions.swift

import CoreGraphics
import SpriteKit

public func + (left: CGPoint, right: CGPoint) -> CGPoint 
   return CGPoint(x: left.x + right.x, y: left.y + right.y)


public func += (left: inout CGPoint, right: CGPoint) 
   left = left + right

第 6 步: 在 didMove(toView:) 中调用 setUpBackgrounds 方法

override func didMove(to view: SKView) 

    setUpBackgrounds()


第 7 步: 最后调用 update(_ currentTime) 方法中的 updateBackgroundupdateGroundMovement 方法。更新代码如下:

override func update(_ currentTime: TimeInterval) 
    if lastUpdateTimeInterval == 0 
        lastUpdateTimeInterval = currentTime
    

    deltaTime = currentTime - lastUpdateTimeInterval
    lastUpdateTimeInterval = currentTime

    //MARK:- Last step:- add these methods here
    updateBackground()
    updateGroundMovement()

【讨论】:

以上是关于如何在 spriteKit swift 4 中制作无限背景的主要内容,如果未能解决你的问题,请参考以下文章

如何制作一个不会不加速物体的力SpriteKit Swift

Swift / SpriteKit:如何创建水滴效果?

无法使应用程序进入主菜单(Swift 4 SpriteKit)

如何在 Sprite Kit / Swift 中将文本环绕在一个圆圈中

如何使用 swift 使用带有 spriteKit 的情节提要

SpriteKit, Swift 2.0 - 在游戏地图上生成对象