LoginSignup
15

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-05-24

はじめに

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

sample.gif Target.png

ゲームについて

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で悩んでいたのですが、この機会にまとめることができて良かったです。

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

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15