对于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 重载)
- ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift
- ios – Swift SpriteKit委托模式
- ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?
- ios – 将GameViewController.swift链接到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
我不知道如何在Swift中实现这一点.是否可以手动设置速度?
Ps:我没有转换obj的技能. C进入swift(新手到Xcode dev.)
解决方法
您必须公开声明这两个节点
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委托模式
我有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?
我已经搜索了一个答案“创建一个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
解决方法
制作常规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 3和SpriteKit:游戏结束后重置GameScene的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ios – Spritekit游戏中无尽的滚动(重复)背景 – Swift、ios – Swift SpriteKit委托模式、ios – 使用swift和spriteKit如何围绕节点外的点旋转SKSpriteNode?、ios – 将GameViewController.swift链接到GameScene.swift的相关信息,请在本站寻找。
本文标签: