在SpriteKit中创建按钮:Swift

我想在SpriteKitSKScene中创建一个按钮,将视图发送到另一个视图控制器。

我尝试使用“performSegue with identifier”,但显然SKScene不支持此function。 如何使用SpriteKit创建一个将视图发送到另一个视图的SpriteKit

这是我尝试用来执行此操作的代码。

带有“HomeButton.prepareForSegueWithIdentifier()”的行只是一个例子。 它实际上不会让我添加“prepareForSegue”部分,它不支持它<—我的意思是,当我去添加它时,它是无法识别的。

 class GameOverScene: SKScene { var HomeButton: SKNode! = nil init(size: CGSize, won: Bool) { super.init(size: size) backgroundColor = SKColor.whiteColor() HomeButton = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 100, height: 100)) HomeButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) HomeButton.userInteractionEnabled = true self.addChild(HomeButton) let message = won ? "You Won!" : "You Lose!" let label = SKLabelNode(fontNamed: "Title 1") label.text = message label.fontSize = 40 label.fontColor = SKColor.blackColor() label.position = CGPoint(x: size.width/2, y: size.height/2) addChild(label) runAction(SKAction.sequence([SKAction.waitForDuration(3.0), SKAction.runBlock() { let reveal = SKTransition.flipHorizontalWithDuration(0.5) let scene = GameScene(size: size) self.view?.presentScene(scene, transition: reveal) } ])) } override func touchesEnded(touches: Set, withEvent event: UIEvent?) { for touch: AnyObject in touches { let location = touch.locationInNode(self) if HomeButton.containsPoint(location) { HomeButton.prepareForSegueWithIdentifier() } } } 

注意:我尝试过使用按钮,但它们不适用于SKScene。

如果有任何混淆,我会回应。

如果你需要在SpriteKit创建一个按钮,我认为这个按钮必须有所有或部分可用的动作来做你想做的任何事情(就像UIButton所做的那样)

在这里,您可以找到一个构建SpriteKit按钮的简单类,称为FTButtonNode:

 class FTButtonNode: SKSpriteNode { enum FTButtonActionType: Int { case TouchUpInside = 1, TouchDown, TouchUp } var isEnabled: Bool = true { didSet { if (disabledTexture != nil) { texture = isEnabled ? defaultTexture : disabledTexture } } } var isSelected: Bool = false { didSet { texture = isSelected ? selectedTexture : defaultTexture } } var defaultTexture: SKTexture var selectedTexture: SKTexture var label: SKLabelNode required init(coder: NSCoder) { fatalError("NSCoding not supported") } init(normalTexture defaultTexture: SKTexture!, selectedTexture:SKTexture!, disabledTexture: SKTexture?) { self.defaultTexture = defaultTexture self.selectedTexture = selectedTexture self.disabledTexture = disabledTexture self.label = SKLabelNode(fontNamed: "Helvetica"); super.init(texture: defaultTexture, color: UIColor.whiteColor(), size: defaultTexture.size()) userInteractionEnabled = true //Creating and adding a blank label, centered on the button self.label.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Center; self.label.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center; addChild(self.label) // Adding this node as an empty layer. Without it the touch functions are not being called // The reason for this is unknown when this was implemented...? let bugFixLayerNode = SKSpriteNode(texture: nil, color: UIColor.clearColor(), size: defaultTexture.size()) bugFixLayerNode.position = self.position addChild(bugFixLayerNode) } /** * Taking a target object and adding an action that is triggered by a button event. */ func setButtonAction(target: AnyObject, triggerEvent event:FTButtonActionType, action:Selector) { switch (event) { case .TouchUpInside: targetTouchUpInside = target actionTouchUpInside = action case .TouchDown: targetTouchDown = target actionTouchDown = action case .TouchUp: targetTouchUp = target actionTouchUp = action } } /* New function for setting text. Calling function multiple times does not create a ton of new labels, just updates existing label. You can set the title, font type and font size with this function */ func setButtonLabel(title: NSString, font: String, fontSize: CGFloat) { self.label.text = title as String self.label.fontSize = fontSize self.label.fontName = font } var disabledTexture: SKTexture? var actionTouchUpInside: Selector? var actionTouchUp: Selector? var actionTouchDown: Selector? weak var targetTouchUpInside: AnyObject? weak var targetTouchUp: AnyObject? weak var targetTouchDown: AnyObject? override func touchesBegan(touches: Set, withEvent event: UIEvent?) { if (!isEnabled) { return } isSelected = true if (targetTouchDown != nil && targetTouchDown!.respondsToSelector(actionTouchDown!)) { UIApplication.sharedApplication().sendAction(actionTouchDown!, to: targetTouchDown, from: self, forEvent: nil) } } override func touchesMoved(touches: Set, withEvent event: UIEvent?) { if (!isEnabled) { return } let touch: AnyObject! = touches.first let touchLocation = touch.locationInNode(parent!) if (CGRectContainsPoint(frame, touchLocation)) { isSelected = true } else { isSelected = false } } override func touchesEnded(touches: Set, withEvent event: UIEvent?) { if (!isEnabled) { return } isSelected = false if (targetTouchUpInside != nil && targetTouchUpInside!.respondsToSelector(actionTouchUpInside!)) { let touch: AnyObject! = touches.first let touchLocation = touch.locationInNode(parent!) if (CGRectContainsPoint(frame, touchLocation) ) { UIApplication.sharedApplication().sendAction(actionTouchUpInside!, to: targetTouchUpInside, from: self, forEvent: nil) } } if (targetTouchUp != nil && targetTouchUp!.respondsToSelector(actionTouchUp!)) { UIApplication.sharedApplication().sendAction(actionTouchUp!, to: targetTouchUp, from: self, forEvent: nil) } } } 

该Gist中提供了该来源

用法

 let backTexture: SKTexture! = SKTexture(image:"backBtn.png") let backTextureSelected: SKTexture! = SKTexture(image:"backSelBtn.png") let backBtn = FTButtonNode(normalTexture: backTexture, selectedTexture: backTextureSelected, disabledTexture: backTexture,size:backTexture.size()) backBtn.setButtonAction(self, triggerEvent: .TouchUpInside, action: #selector(GameScene.backBtnTap)) backBtn.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame)) backBtn.zPosition = 1 backBtn.name = "backBtn" self.addChild(backBtn) func backBtnTap() { print("backBtnTap tapped") // Here for example you can do: let transition = SKTransition.fadeWithDuration(0.5) let nextScene = MenuScene(size: self.scene!.size) nextScene.scaleMode = .ResizeFill self.scene?.view?.presentScene(nextScene, transition: transition) } 

我已经翻译了Alessandro Ornano对Swift 3.1的回答:

 import SpriteKit class FTButtonNode: SKSpriteNode { enum FTButtonActionType: Int { case TouchUpInside = 1, TouchDown, TouchUp } var isEnabled: Bool = true { didSet { if (disabledTexture != nil) { texture = isEnabled ? defaultTexture : disabledTexture } } } var isSelected: Bool = false { didSet { texture = isSelected ? selectedTexture : defaultTexture } } var defaultTexture: SKTexture var selectedTexture: SKTexture var label: SKLabelNode required init(coder: NSCoder) { fatalError("NSCoding not supported") } init(normalTexture defaultTexture: SKTexture!, selectedTexture:SKTexture!, disabledTexture: SKTexture?) { self.defaultTexture = defaultTexture self.selectedTexture = selectedTexture self.disabledTexture = disabledTexture self.label = SKLabelNode(fontNamed: "Helvetica"); super.init(texture: defaultTexture, color: UIColor.white, size: defaultTexture.size()) isUserInteractionEnabled = true //Creating and adding a blank label, centered on the button self.label.verticalAlignmentMode = SKLabelVerticalAlignmentMode.center; self.label.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.center; addChild(self.label) // Adding this node as an empty layer. Without it the touch functions are not being called // The reason for this is unknown when this was implemented...? let bugFixLayerNode = SKSpriteNode(texture: nil, color: UIColor.clear, size: defaultTexture.size()) bugFixLayerNode.position = self.position addChild(bugFixLayerNode) } /** * Taking a target object and adding an action that is triggered by a button event. */ func setButtonAction(target: AnyObject, triggerEvent event:FTButtonActionType, action:Selector) { switch (event) { case .TouchUpInside: targetTouchUpInside = target actionTouchUpInside = action case .TouchDown: targetTouchDown = target actionTouchDown = action case .TouchUp: targetTouchUp = target actionTouchUp = action } } /* New function for setting text. Calling function multiple times does not create a ton of new labels, just updates existing label. You can set the title, font type and font size with this function */ func setButtonLabel(title: NSString, font: String, fontSize: CGFloat) { self.label.text = title as String self.label.fontSize = fontSize self.label.fontName = font } var disabledTexture: SKTexture? var actionTouchUpInside: Selector? var actionTouchUp: Selector? var actionTouchDown: Selector? weak var targetTouchUpInside: AnyObject? weak var targetTouchUp: AnyObject? weak var targetTouchDown: AnyObject? override func touchesBegan(_ touches: Set, with event: UIEvent?) { if (!isEnabled) { return } isSelected = true if (targetTouchDown != nil && targetTouchDown!.responds(to: actionTouchDown)) { UIApplication.shared.sendAction(actionTouchDown!, to: targetTouchDown, from: self, for: nil) } } override func touchesMoved(_ touches: Set, with event: UIEvent?) { if (!isEnabled) { return } let touch: AnyObject! = touches.first let touchLocation = touch.location(in: parent!) if (frame.contains(touchLocation)) { isSelected = true } else { isSelected = false } } override func touchesEnded(_ touches: Set, with event: UIEvent?) { if (!isEnabled) { return } isSelected = false if (targetTouchUpInside != nil && targetTouchUpInside!.responds(to: actionTouchUpInside!)) { let touch: AnyObject! = touches.first let touchLocation = touch.location(in: parent!) if (frame.contains(touchLocation) ) { UIApplication.shared.sendAction(actionTouchUpInside!, to: targetTouchUpInside, from: self, for: nil) } } if (targetTouchUp != nil && targetTouchUp!.responds(to: actionTouchUp!)) { UIApplication.shared.sendAction(actionTouchUp!, to: targetTouchUp, from: self, for: nil) } } } 

用法:

 func buttonTap() { print("Button pressed") } override func didMove(to view: SKView) { backgroundColor = SKColor.white let buttonTexture: SKTexture! = SKTexture(imageNamed: "button") let buttonTextureSelected: SKTexture! = SKTexture(imageNamed: "buttonSelected.png") let button = FTButtonNode(normalTexture: buttonTexture, selectedTexture: buttonTextureSelected, disabledTexture: buttonTexture) button.setButtonAction(target: self, triggerEvent: .TouchUpInside, action: #selector(GameScene.buttonTap)) button.setButtonLabel(title: "Button", font: "Arial", fontSize: 12) button.position = CGPoint(x: self.frame.midX,y: self.frame.midY) button.zPosition = 1 button.name = "Button" self.addChild(button) } 

我创建了两个.png:

button.png buttonSelected

最简单的解决方案,但可能不是最好的质量,是使用包含图像的SpriteNode并命名它。 之后,使用该场景,您可以轻松对其进行编程,以便在点击时将用户转移到下一个场景:

 class GameScene: SKScene { let button = SKSpriteNode(imageNamed: "yourImgName") override func didMoveToView(view: SKView) { button.name = "btn" button.size.height = 100 button.size.width = 100 button.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 50) self.addChild(button) //Adjust button properties (above) as needed } override func touchesBegan(touches: Set, withEvent event: UIEvent?) { let touch = touches.first let positionInScene = touch!.locationInNode(self) let touchedNode = self.nodeAtPoint(positionInScene) if let name = touchedNode.name { if name == "btn" { let yourNextScene = YourNextScene(fileNamed: "YourNextScene") self.view?.presentScene(yourNextScene!) } } } } 

不要忘记将“YourNextScene”替换为下一个场景的实际名称。