AndEngineでロングタップを実装する

 現在作成中のスライドパズルは、前々回に貼り付けたスクリーンショットのとおり、画面いっぱいに画像を表示しています。
 なので、ロングタップでメニュー画面を表示させたいと考えたのですね。
 もちろん、普通のタップ時はパネルがスライドしなくてはなりません。
 どうしたら良いの?
 
 こんなことは、作り始める前に考えておきましょう。
 
 グーグル先生に尋ねたところ、幸いにも AndEngine GLES2-AnchorCenter にはロングタップを取得するクラスがあるようです。
 実装してみました。
 はまりました。
 
 最終的には、こちらのコード。AndEngine の Scene を継承したサブクラスでの処理が前提ね。

import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.input.touch.TouchEvent;
import org.andengine.input.touch.detector.ContinuousHoldDetector;
import org.andengine.input.touch.detector.HoldDetector;
import org.andengine.input.touch.detector.HoldDetector.IHoldDetectorListener;

public class GameScene extends Scene implements IOnSceneTouchListener, IHoldDetectorListener{
	private ContinuousHoldDetector continuousHoldDetector;
	private boolean isHold = false;
	private boolean isTouchOK = true;
	private long holdTime = 200;
	
	GameScene(){
		setOnSceneTouchListener(this);
		setTouchAreaBindingOnActionDownEnabled(true);
		continuousHoldDetector = new ContinuousHoldDetector(this);
		registerUpdateHandler(continuousHoldDetector);
	}
	
	@Override
	public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent){
		if(isTouchOK){
			// ロングタップ処理後は isHold を放置してここでリセット処理する
			if(isHold){
				isHold = false;
				continuousHoldDetector.reset(); // リセットしないとホールドタイムが累積されてしまう
			}
			continuousHoldDetector.onTouchEvent(pSceneTouchEvent);
			// ロングタップされていない場合の処理
			if(!isHold){
				if (pSceneTouchEvent.isActionUp()){
					isTouchOK = false; // これはなくてもイイのかな
					// タップ時の処理
					// 処理が終わったら isTouchOK = true とする
				}
			}
		}
		return true;
	}
	
	@Override
	public void onHoldStarted(HoldDetector pHoldDetector, int pPointerID, float pHoldX, float pHoldY){
		isTouchOK = false;
 	}

	@Override
	public void onHold(HoldDetector pHoldDetector, long pHoldTimeMilliseconds, int pPointerID, float pHoldX, float pHoldY){
		// onHold() はロングタップ中何度も呼ばれるので、規定時間経過後に1度だけ if 内処理に移る
		if(!isHold && pHoldTimeMilliseconds > holdTime){
			isHold = true;
			// ロングタップ時の処理
			// 処理が終わったら isTouchOK = true とする
			// 処理が終わっても isHold は true のまま
		}
	}
        
	@Override
	public void onHoldFinished(HoldDetector pHoldDetector, long pHoldTimeMilliseconds, int pPointerID, float pHoldX, float pHoldY){
	}
}

と、まあ onHold() の呼び出しに応じて何度もロングタップ処理してしまうわ、continuousHoldDetector のリセットに思い至らず、二度目のタップ時は間を置かずロングタップ処理に入りパネルが動かないわで、相当な時間を費やしました。
 
 onSceneTouchEvent() 内の短いタップ時の処理は onHoldFinished() 内に入れても動く気がするのですが、このロジックで現に動いているので試してはいません。

 「現に動いている」というのが肝要です。