GVKun编程网logo

Swift 3(SpriteKit):游戏结束后重置GameScene(swift 重载)

9

对于Swift3感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解SpriteKit:游戏结束后重置GameScene,并且为您提供关于ios–Spritekit游戏中无尽的滚动(重复)背景–

对于Swift 3感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解SpriteKit:游戏结束后重置GameScene,并且为您提供关于ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift、ios – Swift SpriteKit委托模式、ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?、ios – 将GameViewController.swift链接到GameScene.swift的宝贵知识。

本文目录一览:

Swift 3(SpriteKit):游戏结束后重置GameScene(swift 重载)

Swift 3(SpriteKit):游戏结束后重置GameScene(swift 重载)

我想“重置”和“重启”
GameScene,就好像第一次调用GameScene一样。我已经研究了执行此操作的不同方法,但是每次收到警告时,我都试图将节点添加到已具有父级的父级。但是,在我的代码中,我删除了所有现有节点,因此我对如何重置GameScene感到非常困惑。这就是我现在的操作方式(当我想从头开始重新启动GameScene时调用此代码,并在GameScene类中调用此代码):

let scene = GameScene(size: self.size)scene.scaleMode = .aspectFilllet animation = SKTransition.fade(withDuration: 1.0) self.view?.presentScene(scene, transition: animation)self.removeAllChildren()self.removeAllActions()self.scene?.removeFromParent()

1.Edited:
我意识到为什么收到此警告:“我正在尝试将节点添加到已具有父级的父级中”是因为我将场景的所有变量都包含在类之外并作为全局变量。但是,现在当游戏重新启动时,该游戏位于左下角。为什么会这样,我该如何解决?-
固定

2.编辑:
现在一切正常,但是现在我担心的是deinit{}即使每个节点都被删除并且fps不会随着时间的流逝而被调用。这是我在GameViewController中用于设置场景的内容以及在GameScene中的所有内容(每个与场景相关的实例基本上都是相关的):

import UIKitimport SpriteKitimport GameplayKitvar screenSize = CGSize()class GameViewController: UIViewController {override func viewDidLoad() {    super.viewDidLoad()    if let view = self.view as! SKView? {        // Load the SKScene from ''GameScene.sks''        if let scene = SKScene(fileNamed: "GameScene") {            // Set the scale mode to scale to fit the window            scene.scaleMode = .aspectFill            screenSize = scene.size                 // Present the scene            view.presentScene(scene)        }        view.ignoresSiblingOrder = true        view.showsFPS = true        view.showsNodeCount = true    }}

然后我的GameScene基本上是:

import SpriteKitimport GameplayKitclass GameScene: SKScene, SKPhysicsContactDelegate {//Declare and initialise variables and enumerations heredeinit{print("GameScene deinited")}override func didMove(to view: SKView) {     //Setup scene and nodes}override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {    //Do other things depending on when and where you touch    //When I want to reset the GameScene     let newScene = GameScene(size: self.size)    newScene.anchorPoint = CGPoint(x: 0.5, y: 0.5)    newScene.scaleMode = self.scaleMode    let animation = SKTransition.fade(withDuration: 1.0)    self.view?.presentScene(newScene, transition: animation)}

任何答案将不胜感激:)

答案1

小编典典

如何重置场景?

您只需要在需要时再次呈现一个新的相同场景即可。因此,您做得很好。

可能的泄漏问题?

另外,如果你没有在你的游戏泄漏,意味着没有很强的参考周期,你甚至都不需要self.removeAllChildren()self.removeAllActions()......当然,如果你明确要停止行动过渡动画开始前,使用此方法才有意义。关键是,当场景解除分配时,依赖于该场景的所有对象也应该/也将解除分配。

不过,如果您从一开始就不知道自己在做什么以及如何防止泄漏,例如。您正在使用强大的自我约束功能,这是动作序列的一部分,该行为会一直重复,那么您肯定会有漏洞,self.removeAllActions()可能会有所帮助(在许多情况下,但这不是最终的解决方案)。我建议阅读一般性的捕获列表和ARC,因为仅由于这些情况而了解所有工作原理会很有用。

场景是根节点

调用removeFromParent()场景本身无效。Scene是一个根节点,因此无法在当前上下文中将其删除。如果检查场景的父属性,您会注意到它为零。当然可以将一个场景添加到另一个场景,但是在这种情况下,作为子级添加的场景将充当普通节点。

最后,如何呈现新场景?很简单,像这样:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {    let newScene = GameScene(size: self.size)    newScene.scaleMode = self.scaleMode    let animation = SKTransition.fade(withDuration: 1.0)    self.view?.presentScene(newScene, transition: animation)}

如果某些问题不适合您,则很可能是您泄漏了(意味着您的场景没有被重新分配)。要检查这一点,请在您的GameScene中重写deinit方法中的某处,如下所示:

deinit{print("GameScene deinited")}

为了进一步说明这一点……应该发生的是,您应该呈现一个新场景,应该发生过渡,应该释放一个旧场景,并且应该看到一个具有初始状态的新场景。

同样,覆盖deinit只会告诉您场景是否正确释放。但这不会告诉您原因。由您决定在代码中保留场景的内容。

ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift

ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift

我想为我的spritekit游戏创建一个无尽的滚动背景,iT应该包含一两个图像,它们会重复自己?我找到了这些 one和 two的例子,但它们都是obj. C.

我不知道如何在Swift中实现这一点.是否可以手动设置速度?

Ps:我没有转换obj的技能. C进入swift(新手到Xcode dev.)

解决方法

我找到了一种方法来做到这一点,不知怎的,我设法转换 this obj. C迅速

您必须公开声明这两个节点

let background1 = SKSpriteNode(imageNamed: "bg1")
let background2 = SKSpriteNode(imageNamed: "bg2")

在“didMovetoView”方法中

background1.anchorPoint = CGPointZero
background1.position = CGPointMake(0,0)
background1.zPosition = -15
self.addChild(background1)

background2.anchorPoint = CGPointZero
background2.position = CGPointMake(0,background1.size.height - 1)
background2.zPosition = -15
self.addChild(background2)

并在您添加的“覆盖功能更新(currentTime:CFTimeInterval)”方法中

background1.position = CGPointMake(background1.position.x,background1.position.y - 2)
background2.position = CGPointMake(background2.position.x,background2.position.y - 2)

            if(background1.position.y < -background1.size.height)
            {
                background1.position = CGPointMake(background2.position.x,background1.position.y + background2.size.height )
            }

            if(background2.position.y < -background2.size.height)
            {
                background2.position = CGPointMake(background1.position.x,background2.position.y + background1.size.height)

            }

我不知道这是否是最有效的方式.其他问题提到了For循环.但在我看来这更容易.

ios – Swift SpriteKit委托模式

ios – Swift SpriteKit委托模式

我一直在努力学习如何最近使用代表,实际上似乎在很大程度上理解它.但是我有一个问题.

我有1个GameViewController,1个StartScene和1个MenuScene

在我的GameViewController中,我有两个方法,我想从MenuScene调用.到目前为止,我一直在使用NSNotification,它工作正常但我正在尝试使用委托.

所以我在MenuScene中设置了一个协议

protocol MenuSceneDelegate {
 func gameOver()
 func showGameCenter()
}

我比这样引用它

var menuSceneDelegate: MenuSceneDelegate?

在GameViewController中,我在顶部添加了MenuSceneDelegate.到目前为止,一切都很标准.但是我遇到的主要问题是当我在GameViewController中设置委托时就像这样

let skView = view as! SKView!
    var scene = StartScene(size: skView.bounds.size)

    skView.ignoresSiblingOrder = true
    scene.scaleMode = .Resizefill

    skView.presentScene(scene)

    scene.menuSceneDelegate = self   //Sets delegate to StartScene not MenuScene

它只适用于StartScene.如何将GameViewController委托从StartScene设置为MenuScene.如果我首先展示MenuScene,一切正常.但是我首先介绍了StartScene,因此我试图了解如何将委托设置为MenuScene.

我试过下面这样的东西,但它不起作用,只是似乎没有

var menuScene = MenuScene(size: skView.bounds.size)
 menuScene.menuSceneDelegate = self

我将不胜感激任何帮助或支持.非常感谢你

解决方法

基本上解决方案是在我从开始场景变为游戏场景时设置委托,而不是在开始时.

ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?

ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?

如何围绕任意点在SpriteKit中旋转节点?

我已经搜索了一个答案“创建一个SKNode并将其位置设置到旋转中心.将应该围绕该中心旋转的节点添加到中心节点.将子节点的位置设置为所需的偏移量(即半径,比如说x 100).更改中心节点的旋转属性,使子节点围绕中心点旋转.同样适用于cocos2d btw.“

但我真的不明白如何在代码中写这个:(.我在swift非常初学者,这看起来很难.任何人都可以给我一个代码帮助?

解决方法

经过几个小时的实验,我就这样做了.
var fish: SKSpriteNode = SKSpriteNode(imageNamed: "fish")

    fish.anchorPoint = CGPoint(x:CGFloat(-0.5),y:CGFloat(-0.2)) 
    fish.zPosition = CGFloat(y+0.5)  
    fish.position = CGPoint(x:CGFloat(x),y:CGFloat(-60-96*(y-3)))

    var jump = SKAction.rotatetoAngle(CGFloat(3.14),duration: NSTimeInterval(1))
    fish.runAction(jump)

ios – 将GameViewController.swift链接到GameScene.swift

ios – 将GameViewController.swift链接到GameScene.swift

我已经在main.storyboard上创建了一个UI元素,我需要将其隐藏起来,直到游戏结束并且玩家点击屏幕后才会被忽略. Main.storyboard链接到GameViewController,因为我的所有IBOutlets和IBActions都在那里,我的所有游戏代码都在GameScene中.如何将视图控制器链接到场景,以便弹出图像和按钮仅在游戏结束时出现.非常感谢一些帮助,我已经坚持了很长一段时间了.

解决方法

这似乎是人们对SpriteKit游戏的一个常见问题,所以让我们来看看SpriteKit游戏和UIKit应用之间的区别.

制作常规UIKit应用时,例如YouTube,Facebook,您可以为您看到的每个屏幕/菜单使用ViewControllers,CollectionViews,Views等(主屏幕,频道屏幕,订阅频道屏幕等).所以你会使用UIKit API,如UIButtons,UIImageViews,UILabels,UIViews,UICollectionViews等.为了做到这一点,我们会使用故事板.

另一方面,在SpriteKit游戏中它的工作方式不同.您可以使用SKScenes查看您看到的每个屏幕(MenuScene,SettingsScene,GameScene,GameOverScene等),并且只有1个ViewController(GameViewController).具有SKView的GameViewController将呈现您的所有SKScenes.

所以我们应该使用SpriteKit API(例如SKLabelNodes,SKSpriteNodes,SKNodes等)直接在相关的SKScenes中添加我们的UI.为了做到这一点,我们将使用SpriteKit场景级别编辑器而不是故事板.

因此,一般逻辑是从GameViewController中照常加载第一个SKScene,而不是从相关的SKScenes中加载其余的SKScene.除了默认代码之外,你的GameViewController基本上应该没有代码.您也可以非常轻松地从1个场景转换到另一个场景(GameScene – > GameOverScene).

如果您使用GameViewController作为UI,如果您有多个SKScenes,它会很快变得混乱,因为UI将被添加到GameViewController,因此将添加到所有SKScenes.所以你必须在场景之间转换时删除/显示UI,这将是疯狂的.

要在SpriteKit中添加标签,它将是这样的

class GameScene: SKScene {

  lazy var scoreLabel: SKLabelNode = {
      let label = SKLabelNode(fontNamed: "HelveticaNeue")
      label.text = "SomeText"
      label.fontSize = 22
      label.fontColor = .yellow
      label.position = CGPoint(x: self.frame.midX,y: self.frame.midY)
      return label
  }()

  override func didMove(to view: SKView) {

      addChild(scoreLabel)
  }
}

要创建一个按钮,你基本上创建一个SKSpriteNode并给它一个名字,然后在touchesBegan或touchesEnded中查找它,并在其上运行一个SKAction用于动画和一些代码.

enum ButtonName: String {
     case play
     case share
}

class GameScene: SKScene {

       lazy var shareButton: SKSpriteNode = {
            let button = SKSpriteNode(imageNamed: "ShareButton")
            button.name = ButtonName.share.rawValue
            button.position = CGPoint(x: self.frame.midX,y: self.frame.midY)
            return button
        }()

       override func didMove(to view: SKView) {

             addChild(shareButton)
       }

       /// touches began
       override open func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {

             for touch in touches {
                 let location = touch.location(in: self)
                 let node = atPoint(location)

                 if let nodeName = node.name {
                      switch nodeName {
                      case ButtonName.play.rawValue:
                          // run some SKAction animation and some code
                      case ButtonName.share.rawValue:

                          let action1 = SKAction.scale(to: 0.9,duration: 0.2)
                          let action2 = SKAction.scale(to: 1,duration: 0.2)
                          let action3 = SKAction.run { [weak self] in
                             self?.openShareMenu(value: "\(self!.score)",image: nil) // image is nil in this example,if you use a image just create a UIImage and pass it into the method
                          }
                          let sequence = SKAction.sequence([action1,action2,action3])
                          node.run(sequence)

                      default: 
                          break
                    }
               }
          }
     }
}

为了使这更容易,我将创建一个按钮助手类,一个简单的例子看看这个
https://nathandemick.com/2014/09/buttons-sprite-kit-using-swift/

您还可以查看Apple的示例游戏DemoBots,获取更多功能丰富的示例.

这样你就可以在helper类中拥有诸如动画等内容,而不必为每个按钮重复代码.

对于共享,我实际上会使用UIActivityController而不是那些可能很快就会被弃用的旧社交API.这也允许您通过1 UI共享多个服务,您的应用程序中也只需要1个共享按钮.它可能是你在调用它的SKScene中这样一个简单的函数.

func openShareMenu(value: String,image: UIImage?) {
    guard let view = view else { return }

    // Activity items
    var activityItems = [AnyObject]()

    // Text
    let text = "Can you beat my score " + value
    activityItems.append(text as AnyObject)

    // Add image if valid
    if let image = image {
        activityItems.append(image)
    }

    // Activity controller
    let activityController = UIActivityViewController(activityItems: activityItems,applicationActivities: nil)

    // iPad settings
    if Device.isPad {
        activityController.popoverPresentationController?.sourceView = view
        activityController.popoverPresentationController?.sourceRect = CGRect(x: view.bounds.midX,y: view.bounds.midY,width: 0,height: 0)
        activityController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.init(rawValue: 0)
    }

    // Excluded activity types
    activityController.excludedActivityTypes = [
        UIActivityType.airDrop,UIActivityType.print,UIActivityType.assignToContact,UIActivityType.addToReadingList,]

    // Present
    view.window?.rootViewController?.present(activityController,animated: true)
}

然后在按下正确的按钮时调用它(参见上面的例子)

openShareMenu(value: "\(self.score)",image: SOMEUIIMAGE)

希望这可以帮助

关于Swift 3SpriteKit:游戏结束后重置GameScene的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift、ios – Swift SpriteKit委托模式、ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?、ios – 将GameViewController.swift链接到GameScene.swift的相关信息,请在本站寻找。

本文标签: