[iOS 8] SpriteKit でミニゲームをつくる #8 ボタンみたいなスプライト

ボタンみたいなスプライト

今回は「ピン」をタップしてハンドリングできるようにスプライトをボタンのようにしてみます。
下の画像の赤枠の部分です。

stack_penguin_08_01


まず前提として、今回のゲームではマルチタップは使わないので、できないよう設定を変更しておきます。
GameViewController.swift 内の viewDidLoad メソッドに1行追加します。

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let skView = self.view as SKView
        skView.multipleTouchEnabled = false
        
        .............
        .............
        
    }


では、本題のボタンですが、
SpriteKitでは、cocos2dxでいうところの「MenuButton」が見当たりませんでした。。。
さらに、Sprite Editor内でも配置できるボタンが見当たらなかったので、強引にスプライトをラップしてボタンのような振る舞いができるようにボタンぽいクラスを自作してみました。

こんな感じです。

import SpriteKit

class SpriteButton {
    
    weak var button:SKSpriteNode!
    var upTexture:SKTexture!
    var downTexture:SKTexture!
    var buttonDidTouchBlock: dispatch_block_t!
    
    init(button:SKSpriteNode!,
        atlas:SKTextureAtlas!,
        upTexture:String!,
        downTexture:String!,
        block: dispatch_block_t!)
    {
        self.button = button
        self.upTexture = atlas.textureNamed(upTexture)
        self.downTexture = atlas.textureNamed(downTexture)
        buttonDidTouchBlock = block
        
        button.texture = self.upTexture
    }
    
    deinit {
        button = nil
        upTexture = nil
        downTexture = nil
        buttonDidTouchBlock = nil
    }
    
    func buttonDidTouch(p: CGPoint) {
        if button.containsPoint(p) {
            if buttonDidTouchBlock != nil {
                buttonDidTouchBlock()
            }
        }
        changeUpTexture()
    }
    
    func checkAndChangeTexture(p: CGPoint) {
        if button.containsPoint(p) {
            changeDownTexture()
        } else {
            changeUpTexture()
        }
    }
    
    func changeUpTexture() {
        button.texture = upTexture
    }
    
    func changeDownTexture() {
        button.texture = downTexture
    }
    
    // MARK: - touch
    func touchesBegan(touch: UITouch!) {
        let location = touch.locationInNode(button.parent)
        checkAndChangeTexture(location)
    }
    
    func touchesMoved(touch: UITouch!) {
        let location = touch.locationInNode(button.parent)
        checkAndChangeTexture(location)
    }
    
    func touchesEnded(touch: UITouch!) {
        let location = touch.locationInNode(button.parent)
        buttonDidTouch(location)
    }
    
    func touchesCancelled(touch: UITouch!) {
        changeUpTexture()
    }
    
}


使い方はこんな感じ。

import SpriteKit

class GameScene: SKScene {
    
    var pinSpriteButton:SpriteButton!
    
    override func didMoveToView(view: SKView) {
        // レイヤーを取得する。
        let consoleLayer = childNodeWithName("consoleLayer")

        // テクスチャアトラスを取得する。
        let assetsAtlas = SKTextureAtlas(named: "assets")
        
        // ボタンを生成する。
        pinSpriteButton = SpriteButton(
            button: consoleLayer?.childNodeWithName("pinButton") as SKSpriteNode!,
            atlas: assetsAtlas,
            upTexture: "btn_pin_up",
            downTexture: "btn_pin_down",
            block: pinButtonDidTouch
        )
    }
    
    func pinButtonDidTouch() {
        println("pinButtonDidTouch")
    }
    
    override func willMoveFromView(view: SKView) {
        super.willMoveFromView(view)
        
        // 保持してると危なさそうなのでnilにしときます。
        pinSpriteButton = nil
    }
    
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        pinSpriteButton.touchesBegan(touches.anyObject() as UITouch)
    }
    
    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        pinSpriteButton.touchesMoved(touches.anyObject() as UITouch)
    }
    
    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
        pinSpriteButton.touchesEnded(touches.anyObject() as UITouch)
    }
    
    override func touchesCancelled(touches: NSSet, withEvent event: UIEvent) {
        pinSpriteButton.touchesCancelled(touches.anyObject() as UITouch)
    }
}

作っている途中に、「実は簡単にボタンを使う方法があるのでは、、、」とか、
「ストーリボードにUIButtonを置いて制御した方がよかったのでは、、、」とか、
いろいろ思いましたが、一応完成したので使ってみます。
でも、使い勝手が悪すぎる。。。

次回へつづく。ではでは。

完成品はこちら。つみペンギン
つみペンギン stack_penguin_qrcode

姉妹品はこちら。ペンギン陸上-スプリント-
ペンギン陸上-スプリント- athlete_penguin_sprint_qrcode