2016-07-04 44 views
3

我想在SpriteKitSKScene中創建一個按鈕,該按鈕將視圖發送到另一個視圖控制器。在SpriteKit中創建按鈕:Swift

我試過使用「執行標識符」,但顯然SKScene不支持這個。 我將如何創建一個按鈕,將視圖發送到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<UITouch>, withEvent event: UIEvent?) { 
     for touch: AnyObject in touches { 
      let location = touch.locationInNode(self) 

      if HomeButton.containsPoint(location) { 

       HomeButton.prepareForSegueWithIdentifier() 

      } 
     } 
    } 

注意:我試過使用一個按鈕,但它們在SKScene中不起作用。

如果有任何混淆,我會做出迴應。

+0

對我的作品像往常一樣,所以我不知道你的問題是什麼 有了這個? –

+0

你能解釋一下你試圖做什麼 – user3128464

+1

嘿,如果你能發表一個你嘗試過的例子,並且有人能夠幫助你弄清楚什麼不起作用,那就太好了。 – theatlasroom

回答

3

如果您需要在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<UITouch>, 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<UITouch>, 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<UITouch>, 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) 
     } 
    } 

} 

源在this 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) 
} 
+0

我可以把它發送到viewController而不是另一個SKScene嗎? – Nickolans

+0

當然,我的答案只是一個例子,如果你不知道如何看這個鏈接http://stackoverflow.com/a/30041939/1894067 –

2

最簡單的解決方案,但可能不是最大的質量,是使用一個包含圖像並命名它的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<UITouch>, 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」與您的下一個場景的實際名稱。

4

我有翻譯亞歷山德羅Ornano的回答讓雨燕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<UITouch>, 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<UITouch>, 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<UITouch>, 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) 
} 

我已經創建了兩個巴紐:

button.png buttonSelected