入力が使えないゲームはゲームじゃない!
ってことで、今回はタッチ入力を扱ってみます。
入力を制御するには入力関連のクラスを使えば簡単にできます。
では、その扱いをやってみましょう!
まず、TouchEventObjectクラスを継承したボタンを実装します。
// タッチボタン class TouchButton extends TouchEventObject { // コンストラクタ public TouchButton( TouchManager mngr ) { super( mngr ); m_TouchPos = new PointF(); } // 触れた場所を取得 public PointF GetTouchPos() { return m_TouchPos; } // 更新 @Override public void Update() { } // 指が離れた @Override public void OnTouchUp( PointF pos ) { } // 指がそっと触れた(激しいかもしれない) @Override public void OnTouchDown( PointF pos ) { } // 指が動いた @Override public void OnTouchMove( PointF pos ) { // 移動した位置を記憶 m_TouchPos.set( pos ); } // 指がどこかへ去っていった @Override public void OnTouchOut( PointF pos ) { } private PointF m_TouchPos; }
OnTouchMove()で指が移動した時の位置を覚えています。
その位置をGetTouchPos()で取得できるようにしているだけです。
次にタッチ入力関連のクラスをMainActivityクラスに持たせます。
そして、onCreate()で作成します。
// コンストラクタ public MainActivity() { : : m_TouchWatcher = null; m_TouchMngr = null; m_Button = null; : : } // 作成 @Override public void onCreate( Bundle savedInstanceState ) { : : m_TouchWatcher = new TouchWatcher(); m_TouchMngr = new TouchManager( m_TouchWatcher ); m_Button = new TouchButton( m_TouchMngr ); { m_Button.SetRect( 0, 0, ( int )DrawDevice.DRAW_WIDTH, ( int )DrawDevice.DRAW_HEIGHT ); } : : } : : private TouchWatcher m_TouchWatcher; private TouchManager m_TouchMngr; private TouchButton m_Button;
onCreate()内でTouchWatcherを最初に作ります。
次にTouchManagerを作り、最後にTouchButtonを作ります。
TouchButtonをSetRectで仮想描画領域全域をタッチ領域として設定しています。
準備ができたら次にタッチイベントをTouchWatcherに渡します。
// タッチイベント @Override public boolean onTouchEvent( MotionEvent event ) { final float orgTouchPosX = event.getX(); final float orgTouchPosY = event.getY(); PointF touchPos = m_DrawDevice.GetSprite().ScreenPosToDrawPos( new PointF( orgTouchPosX, orgTouchPosY )); TouchWatcher.ACTION action; switch( event.getAction()) { case MotionEvent.ACTION_DOWN: action = TouchWatcher.ACTION.ACTION_DOWN; break; case MotionEvent.ACTION_MOVE: action = TouchWatcher.ACTION.ACTION_MOVE; break; case MotionEvent.ACTION_UP: action = TouchWatcher.ACTION.ACTION_UP; break; default: return true; } if( !m_TouchWatcher.AddAction( action, touchPos )) { System.err.println( "TouchEventOverFlow!!" ); } return true; }
タッチイベントをTouchWatcherに渡すために変換しています。
ほぼそのまま変換できるので迷うことはないと思います。
問題はタッチされた時の座標です。
タッチ位置はスクリーン座標で来るのでそのまま使うと仮想描画領域とずれてしまいます。
そこで、スクリーン座標を仮想描画領域の座標系に変換するために
Sprite#ScreenPosToDrawPos()を呼び出します。
これで座標系を気にせずタッチ位置を取得できるようになります。
(本当は座標変換クラスを作ってそれをSpriteクラスや
TouchWatcherクラスに渡すほうがスッキリします)
最後に、実際にタッチ関連のクラスを使ってみます。
// 描画フレーム @Override public void onDrawFrame( GL10 gl ) { // シーンの更新 m_DrawDevice.Begin( gl ); { m_TouchMngr.Update(); : : // 描画 if( m_Image != null ) { Sprite sprite = m_DrawDevice.GetSprite(); DrawParam drawParam = sprite.CreateDrawParam( m_Image ); { // 追加 drawParam.m_Pos.set( m_Button.GetTouchPos()); drawParam.m_ImageRect.left = 0; drawParam.m_ImageRect.top = 0; drawParam.m_ImageRect.right = m_Image.GetWidth(); drawParam.m_ImageRect.bottom = m_Image.GetHeight(); } sprite.Draw( drawParam ); } } m_DrawDevice.End(); // タッチイベント監視人更新 m_TouchWatcher.Update(); }
シーン更新時にTouchManagerを更新します。
そしてシーン終了時にTouchWatcherを更新します。
今回はタッチした位置をわかりやすくするためヒットマンの描画位置を変えてます。
(コメントで追加と書いてある部分)
結果はこんな感じです。
あのヒットマンがいる辺りをタッチしました。
うまく入力できたようです。
これでなんとなくゲームが作れそうな気がしますね。
では、次はゲームっぽい画面を作ってみましょう!