web-dev-qa-db-ja.com

Xcode&Swift-UIScrollView内のUIViewのユーザータッチの検出

Flappy Birdに似たゲームを作成していますが、ユーザーは、鳥を飛ばすためにタップするのではなく、画面に指を置いて障害物を避けます。

UIViewを障害物として使用するUIScrollViewを使用してこれを行っています。ユーザーがUIViewに触れると、ゲームオーバーです。

UIScrollView内からUIViewのユーザータッチを検出するにはどうすればよいですか? Xcode Beta 4ではSwiftを使用しています。

編集:これはゲームのスクリーンショットです

This is screenshot of the game

ご覧のとおり、ユーザーは上にスクロールしながら灰色のブロック(UIView)の間で指を動かします。

26
user2397282

スクロールビューのuserInteractionEnabledNOに設定すると、UIViewControllerUIResponderのサブクラスであるため、View Controllerはタッチイベントの受信を開始します。 View Controllerでこれらのメソッドの1つ以上をオーバーライドして、これらのタッチに応答できます。

  • touchesBegan:withEvent:
  • touchesMoved:withEvent:
  • touchesEnded:withEvent:
  • touchesCancelled:withEvent:

これを行う方法を示すサンプルコードをいくつか作成しました。

class ViewController: UIViewController {
    @IBOutlet weak var scrollView: UIScrollView!

    // This array keeps track of all obstacle views
    var obstacleViews : [UIView] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create an obstacle view and add it to the scroll view for testing purposes
        let obstacleView = UIView(frame: CGRectMake(100,100,100,100))
        obstacleView.backgroundColor = UIColor.redColor()
        scrollView.addSubview(obstacleView)

        // Add the obstacle view to the array
        obstacleViews += obstacleView
    }

    override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
        testTouches(touches)
    }

    override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
        testTouches(touches)
    }

    func testTouches(touches: NSSet!) {
        // Get the first touch and its location in this view controller's view coordinate system
        let touch = touches.allObjects[0] as UITouch
        let touchLocation = touch.locationInView(self.view)

        for obstacleView in obstacleViews {
            // Convert the location of the obstacle view to this view controller's view coordinate system
            let obstacleViewFrame = self.view.convertRect(obstacleView.frame, fromView: obstacleView.superview)

            // Check if the touch is inside the obstacle view
            if CGRectContainsPoint(obstacleViewFrame, touchLocation) {
                println("Game over!")
            }
        }
    }

}
50
s1m0n

次のように、プログラムでジェスチャー認識を追加できます。

var touch = UITapGestureRecognizer(target:self, action:"action")
scrollView.addGestureRecognizer(touch)

ただし、このジェスチャレコグナイザーは機能しません。 UITapGestureRecognizerは、タップアンドホールドではなく、タップに対してのみ戻り、UILongPressGestureRecognizerは場所に関する情報を提供しないため、UIPanGestureRecognizerを使用する必要があります。タッチがどれだけ動いたかを常に示します。

var touch = UIPanGestureRecognizer(target:self, action:"handlePan")
scrollView.addGestureRecognizer(touch)

@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    recognizer.setTranslation(CGPointZero, inView: self.view)
}

一定の「平行移動」を使用してオブジェクトを移動できます。これは、人が指をスライドさせた距離を表します。それに鳥の位置を加えて、鳥を新しいポイントに移動します。この関数が呼び出された後、変換をゼロにリセットする必要があります。

編集:ゲームの形式では、このコードが最適な方法です。

したがって、指の位置を見つけるためのコードはすべて次のようになります。

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInView(yourScrollView)
    }
}


@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    var currentLocation : CGPoint = CGPointMake(location.x+translation.x, location.y+translation.y)
    recognizer.setTranslation(CGPointZero, inView: self.view)
}

currentLocationは、現在のタッチの位置を含むCGPointであり、指がスライドした場所です。回避するビューの作成方法がわからないので、currentLocationのy座標を使用して、そのyで回避するビューのx境界を決定し、<または>コンパレーターを使用して決定する必要がありますタッチのx境界がこれらのビューのいずれかにある場合。

注:場所を宣言して、handlePanでアクセスできるようにする必要があります。

var location : CGPoint = CGPointZero
15
trumpeter201