触れる!反応する!何かが起こる!?

触れる!反応する!何かが起こる!?




入力が使えないゲームはゲームじゃない!
ってことで、今回はタッチ入力を扱ってみます。

入力を制御するには入力関連のクラスを使えば簡単にできます。
では、その扱いをやってみましょう!

まず、TouchEventObjectクラスを継承したボタンを実装します。

MainActivity.java
//  タッチボタン
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を更新します。

今回はタッチした位置をわかりやすくするためヒットマンの描画位置を変えてます。
(コメントで追加と書いてある部分)
結果はこんな感じです。

タッチしてみた

あのヒットマンがいる辺りをタッチしました。
うまく入力できたようです。
これでなんとなくゲームが作れそうな気がしますね。

では、次はゲームっぽい画面を作ってみましょう!



<前のページ
次のページ>