AppleWatchKitとSpriteKitでスペースシューティングゲームを作ってみた

  • 9
    いいね
  • 0
    コメント

はじめに

こんにちは:leaves:
私は個人的にSpriteKitが好きで、WatchKitの練習とタッチイベントの確認のためにAppleWatch上で動く、簡単なゲームを作ってみたので共有したいと思います(ゲームが面白くないのは秘密です...)

sample.gif Target.png

https://github.com/KikurageChan/TimeCosmos

ゲームについて

272px × 340pxととても小さな画面でのスワイプ動作はやりにくく、UIデザイン的にも問題があるかもしれないので、操作をタップのみにしたり、AppleWatchの横についているネジ(Digital Crown)を利用する方が良かったかもしれません...

実装について

プロジェクトの作成方法などはこちらが大変参考になりました
Apple WatchでSpriteKitを使ってアニメーション ワンダープラネットブログ

WKInterfaceControllerなどを用意してしまえば、通常のSpriteKitでゲームを作る時と、そんなに変わらないと感じました。

自動生成される.sksファイルのシーンのアンカーポイントがデフォルトで中心になっているので、左下(x: 0, y: 0)に変更しておきます。

AppleWatchの画面サイズについて

ステータスバーを除いたコンテンツの領域はWKInterfaceController内のcontentFrameプロパティで取得できます

Screen.png

このサイズに合わせてGameScene.sksなどのシーンのサイズを調節すると、
画面が見やすくて良い感じです。

AppleWatchのタッチイベントについて

AppleWatchUIKitの概要とは異なっていて、UIViewを利用することができません。
よって、UIViewなどが持つタッチイベントを取得するUIResponderのメソッドが利用できないのです。

//利用できないメソッドたち
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {}

そこで別の方法として、UIViewUITapGestureRecognizerのようなジェスチャーを利用してタッチイベントを取得することができるようです。(UIViewの座標とSKNodeの座標の違いに気をつけます)

  • WKLongPressGestureRecognizerminimumPressDuration = 0に設定(TouchBeganStateをすぐに取得するため)
  • ロングタップ時のメソッドを定義(今回はIB接続)
  • location(ofTouch: in :)が利用できないので、座標計算するExtensionを追加
@IBAction func longTap(_ sender: WKLongPressGestureRecognizer) {
    let point = sender.locationInView()
    switch sender.state {
    case .began:
        print("touchBegan:\(point)")
    case .changed:
        print("touchMoved:\(point)")
    case .ended:
        print("touchEnded:\(point)")
    default: break
    }
}

extension WKGestureRecognizer {
    //シーンのアンカーポイントはデフォルトの(x: 0, y: 0)を利用
    func locationInView() -> CGPoint {
        let location = locationInObject()
        let bounds = objectBounds()
        return CGPoint(x: location.x, y: bounds.maxY - location.y)
    }
}

これでAppleWatch×SpriteKitのタッチ座標を取得することでノードをドラッグできるようになりました。

touch.gif

おわりに

AppleWatchのゲームは画面が小さく、操作のための領域を取ると、ゲーム画面が減ってしまうので、UIとの兼ね合いが難しいと感じました。
また、AppleWatchのTouchEventで悩んでいたのですが、この機会にまとめることができて良かったです。

参考にさせていただいた記事

見て頂いてありがとうございます。