Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

はじめに

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

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

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

KikurageChan
見て頂いてありがとうございます。
https://kikuragechan.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした