CSS調整

2016年12月1日

libgdxで複数のInputProcessorを扱う

例えば、UIのレイヤの入力とは別にゲームのレイヤでも入力を取りたい場合、InputMultiplexerを使うといいみたい
自分が今回やりたかったケースは、スマホゲームによくある、ボタン系をそのままに後ろのマップをスクロールできるような感じ

UIをStageで定義していて、StageはInputAdapterを継承している
これに対して後ろのレイヤをタッチ操作でスクロールする処理を施そうと思い、
GestureDetectorを使おうと考えた

しかしこちらもInputAdapterを継承している為、UIの入力との同時設定が直にはできない
こんな時に、Gdx.input.inputProcessorへ複数を登録する為に使えるのがInputMultiplexer
InputMultiplexer自体の使い方は単純で、インスタンス化して上位レイヤから順にInputProcessorを登録していくだけ

以下、サンプルコード
val im = InputMultiplexer()
// uiのステージを先に登録
im.addProcessor(ui.stage)
im.addProcessor(GestureDetector(CameraScroller()))
Gdx.input.inputProcessor = im

// pan操作でcameraを動かすだけのリスナー
private inner class CameraScroller : GestureDetector.GestureListener {
    override fun pan(x: Float, y: Float, deltaX: Float, deltaY: Float): Boolean {
        camera.translate(-deltaX, deltaY)
        return true
    }
    override fun panStop(x: Float, y: Float, pointer: Int, button: Int): Boolean = true

    override fun pinch(initialPointer1: Vector2?, initialPointer2: Vector2?, pointer1: Vector2?, pointer2: Vector2?): Boolean = false
    override fun pinchStop() {}
    override fun longPress(x: Float, y: Float): Boolean = false
    override fun fling(velocityX: Float, velocityY: Float, button: Int): Boolean = false
    override fun touchDown(x: Float, y: Float, pointer: Int, button: Int): Boolean = false
    override fun zoom(initialDistance: Float, distance: Float): Boolean = false
    override fun tap(x: Float, y: Float, count: Int, button: Int): Boolean = false
}

// あんまりオーバーライドしないならアダプター版もあるヨ
private inner class CameraScroller : GestureDetector.GestureAdapter() {
    override fun pan(x: Float, y: Float, deltaX: Float, deltaY: Float): Boolean {
        camera.translate(-deltaX, deltaY)
        return true
    }
    override fun panStop(x: Float, y: Float, pointer: Int, button: Int): Boolean = true
}


登録されたInputProcessorは登録順で呼び出される
同じイベントが順次発火するようにしていた場合に重要になるのが各イベントの戻り値で、先に実行されたInputProcessorがtrueを返すと後のInputProcessorのイベントが呼び出されなくなるっぽい
いわゆるstopPropagation(cancelBubble)みたいな使い方ができるわけだ(けど若干クセがある)
この辺はInputMultiplexerのソースを見るとわかりやすいかも