Android」カテゴリーアーカイブ

Android

Android エスプガルーダ2/怒首領蜂第復活

iPhone 版やりこんでいたので Android 版も購入しました。
エスプガルーダⅡと怒首領蜂大復活
手持ちで対応していた端末は下記の 3台。

・Galaxy S2 SC-02C (Exynos4210)
・EVO 3D ISW12HT (MSM8660)
・Optimus Pad L-06C (Tegra250) ※2011/10/21現在 エスプガルーダIIのみ

● Galaxy S2 SC-02C

高速です。描画の処理落ちもなくタッチの遅延もなく非常に良好です。
画面はコントラストが高く他機種に比べて濃い発色となります。
気になる場合は設定→画面→スクリーンモード
HDMI アダプタを使って外部モニタでのプレイもあり。

● EVO 3D ISW12HT

推奨端末ですが描画は処理落ちがあります。
Adreno 220 は 3D 性能が高かったのでどこが原因かは不明。
タッチの遅延は少なく追従性は比較的良好です。
Rendering skip off で難易度が下がるので上達した気になる。

● Optimus Pad L-06C

エスプガルーダⅡだけですが、処理落ちもなく描画は高速です。
ただタッチパネルの入力遅延が大きく、操作に対して自機が遅れて
ついてくる動きになっています。

2011/10/26追記 怒首領蜂大復活も L-06C 対応になりました。

対応端末のスペックを調べてみました。

◎推奨端末
Galaxy S SC-02B        S5PC110 Cortex-A8 1GHz      PVR SGX540  512MB
Galaxy S2 SC-02C       S5PC210 Cortex-A9 x2 1.2GHz Mali-400MP    1GB
PHOTON ISW11M          Tegra250 Cortex-A9 x2 1GHz  ULP GeForce   1GB
EVO 3D ISW12HT         MSM8660 Scorpion x2 1.2GHz  Adreno 220    1GB

◎対応端末
Xperia arc  SO-01C     MSM8255 Scorpion 1GHz       Adreno 205  512MB
Xperia acro SO-02C     MSM8255 Scorpion 1GHz       Adreno 205  512MB
Xperia ray  SO-03C     MSM8255 Scorpion 1GHz       Adreno 205  512MB
Xperia play SO-01D     MSM8255 Scorpion 1GHz       Adreno 205  512MB
Optimus bright L-07C   OMAP3630 Cortex-A8 1GHz     PVR SGX530  512MB
Optimus Pad L-06C      Tegra250 Cortex-A9 x2 1GHz  ULP GeForce   1GB
AQUOS PHONE SH-12C     MSM8255 Scorpion 1.4GHz     Adreno 205  512MB
AQUOS PHONE SH-13C     MSM8255 Scorpion 1GHz       Adreno 205  512MB
MEDIAS WP N-06C        MSM8255 Scorpion 1GHz       Adreno 205  512MB
Panasonic P-07C        OMAP3630 Cortex-A8 1GHz     PVR SGX530  512MB
FUjitsu F-12C          MSM8255 Scorpion 1GHz       Adreno 205  512MB
Galaxy Tab SC-01C      S5PC110 Cortex-A8 1GHz      PVR SGX540  512MB

SHARP IS05             MSM8655 Scorpion 1GHz       Adreno 205  512MB
Xperia acro IS11S      MSM8655 Scorpoin 1GHz       Adreno 205  512MB
AQUOS PHONE IS11SH     MSM8655 Scorpion 1.4GHz     Adreno 205  512MB
AQUOS PHONE IS12SH     MSM8655 Scorpion 1.4GHz     Adreno 205  512MB
INFOBAR A01            MSM8655 Scorpion 1.4GHz     Adreno 205  512MB
G'zOne IS11CA          MSM8655 Scorpion 1GHz       Adreno 205  512MB
REGZA Phone IS11T      MSM8655 Scorpion 1.4GHz     Adreno 205  512MB
MIRACH IS11PT          MSM8655 Scorpion 1.0GHz     Adreno 205  512MB

Desire HD 001HT        MSM8255 Scorpion 1GHz       Adreno 205  768MB
GALAPAGOS 003SH        MSM8255 Scorpion 1GHz       Adreno 205  512MB
GALAPAGOS 005SH        MSM8255 Scorpion 1GHz       Adreno 205  512MB
AQUOS PHONE 006SH      MSM8255 Scorpion 1.4GHz     Adreno 205  512MB
AQUOS HYBRID 007SH     MSM8255 Scorpion 1GHz       Adreno 205  512MB
Sweety 003P            OMAP3630 Cortex-A8 1GHz     PVR SGX530  512MB
ZTE 008Z               MSM8255 Scorpion 1GHz       Adreno 205  512MB
Vision 007HW           MSM8255 Scorpion 1GHz       Adreno 205  512MB
AQUOS PHONE 009SH      MSM8255 Scorpion 1GHz       Adreno 205  512MB
DM009SH                MSM8255 Scorpion 1GHz       Adreno 205  512MB

端末一覧と比べてみると、ちょうど Adreno 205/PVR SGX530 以上の端末が
動作対象となっています。
CPU/GPU 等の搭載プロセッサで線引きが行われているようです。

GPU 性能で下記のようにグループ分けしてみました。
Group 2 以上が今回の動作対象となっています。

GPU別
G3   | Adreno 220, PVRSGX543MP2, Mali-400MP
G2   | Adreno 205, PVRSGX530/535/540, ULP GeForce(Tegra250)
G1   | Adreno 200, Z430
G0   | ARMv6 (ARM11)

Chip (CPU)
G3   | MSM8260/8660, Exynos4210, A5
G2.5 | Tegra250
-------- ↑ Dual core CPU ------------------------
G2   | MSM8255/8655, S5PC110, OMAP3630, A4
G1   | QSD8250/8650, i.MX515
-------- ↑ ARMv7 --------------------------------
G0   | MSM7227, MSM7225

関連エントリ
iPhone 3GS エスプガルーダII ESPGALUDA2

Android 4.0 Ice Cream Sandwich SDK と AVD

Emulator (AVD) が ARMv7 になっているようです。
neon ありでデフォルトの RAM 容量も 512MB。
(以前は ARMv5TE)

Processor	: ARMv7 Processor rev 0 (v7l)
BogoMIPS	: 405.50
Features	: swp half thumb fastmult vfp edsp neon vfpv3 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc08
CPU revision	: 0

ndk も armeabi-v7a のまま走らせられるようになります。

SDK Manager 周りの UI が変更されているようです。
下記インストール手順のページを修正しました。

Android SDK/NDK install 方法

Android Java で OpenGL ES 2.0 を使う

Android の OpenGL ES 2.0 対応は OS 2.0 Eclair からです。
まず NDK で使えるようになり、2.2 Froyo (API Level 8) では Java からも
呼び出せるようになっています。
実際に使ってみました。

2.0 への切り替えは GLSurfaceView の setEGLContextClientVersion( 2 ) です。

public class MarkerView extends GLSurfaceView {
    public MarkerView( Context context ) {
        super( context );
        setEGLContextClientVersion( 2 );    // GLES 2.0
        setRenderer( new MarkerRenderer( context ) );
    }
}

GLSurfaceView.Renderer には GL10 の interface が引数で渡されますが使いません。
android.opengl.GLES20 の static メソッドをそのまま呼び出します。

public class MarkerRenderer implements GLSurfaceView.Renderer {

  ~

    public void onSurfaceChanged( GL10 ugl, int w, int h ) {
        GLES20.glViewport( 0, 0, w, h );
    }

    public void onDrawFrame( GL10 ugl ) {
        GLES20.glClearColor( 0.0f, 0.0f, 0.5f, 0.0f );
        GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT );

        GLES20.glEnable( GLES20.GL_CULL_FACE );
        GLES20.glFrontFace( GLES20.GL_CW );
        GLES20.glCullFace( GLES20.GL_BACK );

        ~
        GLES20.glBindBuffer( GLES20.GL_ELEMENT_ARRAY_BUFFER, ibuffer );
        GLES20.glDrawElements( GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, 0 ); // ← できない
    }
}

試してみて気がついたのですが、Android 2.2 の Java からは
VertexBuffer/IndexBuffer (VBO) が使えないようです。

glVertexAttribPointer() や glDrawElements() の最後の引数に、
NULL やアドレスのオフセットを与えることができないからです。

Android 2.3 (API Level 9) では修正されており、足りない命令が追加
されていました。

↓また下のスライドに説明があります。

io2011-opengl-for-android

Android 2.2 の場合は、glVertexAttribPointer() / glDrawElements()
の 2命令を jni (NDK) を使って自分で作ればこの問題を回避できるそうです。

Android OpenWnn のコンパイル方法メモ

親指 Pie さんの下記のページを参考にさせて頂きました。

親指Pie OpenWnnのビルド

簡単にビルドできることがわかったので書いておきます。
Android 自体のビルドは不要です。

(1) Android ソースリスト入手

下記のページの通り進めます。
VirtualBox + Ubuntu 11.04 x64 (natty) を使いました。

Android open source project : Initializing a Build Environment

注意: 2011/09/30 現在 android.git.kernel.org にアクセスできないようです。
(この記事の手順を確認したのは 2011/09/01)

(2) OpenWnn の参照

個別ビルドするため別の場所に移動します。Windows でも構いません。
ソースコード中 packages/inputmethods/OpenWnn フォルダをまるごと任意の
場所にコピーします。

コピーしたあと OpenWnn の中のフォルダ libs を jni にリネームします。

(3) Android SDK/NDK install

Android のアプリケーション開発環境を整えます。
SDK と NDK 両方必要です。

Android SDK/NDK install から実機の接続、サンプルの実行まで

(4) ビルド

ndk を使った通常のアプリと同じ手順でビルドできます。
以下 Windows を想定。

プロジェクト作成

 1. Eclipse 起動
 2. File → New → Project
 3. Android を開いて Android Project を選択して [Next]
 4. Create project from existing source を選択
 5. Browse.. ボタンで OpenWnn フォルダを選択して [OK]
 6. Android 2.2 を選択して [Finish]

NDK でコンパイル

 1. cygwin shell で OpenWnn フォルダに移動
 2. ndk-build を実行 ( ~/android-ndk-r6b/ndk-build を実行)

Eclipse 上でビルド&実行

 1. プロジェクト (default だと OpenWnnControlPanelJAJP) を選択して
   右ボタンのメニューから「Refresh」を実行
 2. 同じようにプロジェクトの右ボタンメニューから
   Run As → Android Application
 3. Emulator or 実機の設定画面から Japanese IME を有効にする

Android 3.1 と GamePad のイベントの詳細 (2)

引き続き Android OS 3.1 に Xbox360 Pad と Playstation3 Pad を
つないだ場合の値の取り方です。(前回)
アナログスティックの情報は onGenericMotionEvent で受け取れます。

@Override
public boolean onGenericMotionEvent( MotionEvent event ) {
  float posx= event.getAxisValue( MotionEvent.AXIS_X );
  ~
}

入力値に差が生じた場合のみイベントが発生します。
getX()/getY() は getAxisValue() の AXIS_X, AXIS_Y と同値です。

対応付は下記の通り

axis            Xbox360Pad   PS3 Pad       範囲  Source
-----------------------------------------------------------------------
AXIS_X          左stick 横   左stick 横   -1~1  SOURCE_CLASS_JOYSTICK
AXIS_Y          左stick 縦   左stick 縦   -1~1  SOURCE_CLASS_JOYSTICK
AXIS_Z          右stick 横   右stick 横   -1~1  SOURCE_CLASS_JOYSTICK
AXIS_RZ         右stick 縦   右stick 縦   -1~1  SOURCE_CLASS_JOYSTICK
AXIS_HAT_X      十字キー横   ----         -1~1  SOURCE_CLASS_JOYSTICK
AXIS_HAT_Y      十字キー縦   ----         -1~1  SOURCE_CLASS_JOYSTICK
AXIS_LTRIGGER   Lトリガ      L2            0~1
AXIS_RTRIGGER   Rトリガ      R2            0~1

左上が (-1,-1), 右下が (1,1)

Xbox360 Pad のみ、デジタル方向ボタン(十字キー) が MotionEvent の
AXIS_HAT_X/AXIS_HAT_Y を返します。(KeyEvent も発生します)

他にも MotionEvent と同時に KeyEvent を発生させるものがあります。

◎Xbox360 Pad / PS3 Pad
・AXIS_X           KEYCODE_DPAD_LEFT/KEYCODE_DPAD_RIGHT
・AXIS_Y           KEYCODE_DPAD_UP/KEYCODE_DPAD_DOWN

◎PS3 Pad のみ
・AXIS_LTRIGGER    KEYCODE_L2
・AXIS_RTRIGGER    KEYCODE_R2

◎Xbox360 Pad のみ
・AXIS_HAT_X       KEYCODE_DPAD_LEFT/KEYCODE_DPAD_RIGHT
・AXIS_HAT_Y       KEYCODE_DPAD_UP/KEYCODE_DPAD_DOWN

●デジタル方向キーとアナログスティックの区別方法

ここで問題となるのは、左アナログスティックで MotionEvent だけでなく
KeyEvent も発生してしまうことです。
デジタル方向ボタンの代わりに左アナログスティックを使うことができる反面、
アナログとデジタルに異なる操作を割り当てたいときに困ります。

KeyCode だけではこの両者を区別できないので方法を探しました。

Xbox360 Pad の方向キーは AXIS_HAT_X/AXIS_HAT_Y からも値をとれるため
KeyEvent を参照せずにこちらを使えば区別することができます。

PS3 Pad の場合は SOURCE_CLASS で区別できるようです。

訂正 2011/08/11 不要でした。Xbox360 のみ AXIS → KeyCode 変換だけで OK です。

KeyEvent.getSource() & InputDevice.SOURCE_CLASS_MASK

PS3 のみデジタル方向キーが SOURCE_CLASS_BUTTON となります。

◎KeyEvent の SOURCE_CLASS 値

                    Xbox360 Pad              PS3 Pad
--------------------------------------------------------------------
デジタル方向キー    SOURCE_CLASS_JOYSTICK    SOURCE_CLASS_BUTTON
アナログ方向キー    SOURCE_CLASS_JOYSTICK    SOURCE_CLASS_JOYSTICK


◎MotionEvent の情報

                    Xbox360 Pad              PS3 Pad
--------------------------------------------------------------------
デジタル方向キー    AXIS_HAT_X/AXIS_HAT_Y    無し
アナログ方向キー    AXIS_X/AXIS_Y            AXIS_X/AXIS_Y

実際のコード(Activity 抜粋)は下記の通り。
これで Xbox360 Pad / PS3 Pad 共に、デジタル方向ボタンを
KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT を受け取れるようになります。
(プログラムコード訂正しました 2011/08/11 )

final static int   SENDKEY_UP      =   0;
final static int   SENDKEY_DOWN    =   1;

private int mPrevState= 0;

private boolean sendKey( int KeyCode, int up_down ) {
   // 実際のキーコード処理

   ~
}

@Override
public boolean onKeyDown( int KeyCode, KeyEvent event ) {
    return  sendKey( KeyCode, SENDKEY_DOWN );
}

@Override
public boolean onKeyUp( int KeyCode, KeyEvent event ) {
    return  sendKey( KeyCode, SENDKEY_UP );
}

@Override
public boolean onGenericMotionEvent( MotionEvent event ) {
    // Xbox360 の 十字キーはこれで判別
    final int   KEYFLAG_UP      = (1<<0);
    final int   KEYFLAG_DOWN    = (1<<1);
    final int   KEYFLAG_LEFT    = (1<<2);
    final int   KEYFLAG_RIGHT   = (1<<3);
    final float HAT_BORDER= 0.5f;

    float hatx= event.getAxisValue( MotionEvent.AXIS_HAT_X );
    float haty= event.getAxisValue( MotionEvent.AXIS_HAT_Y );

    int code= 0;
    if( hatx < -HAT_BORDER ){
        code|= KEYFLAG_LEFT;
    }
    if( hatx >  HAT_BORDER ){
        code|= KEYFLAG_RIGHT;
    }
    if( haty < -HAT_BORDER ){
        code|= KEYFLAG_UP;
    }
    if( haty >  HAT_BORDER ){
        code|= KEYFLAG_DOWN;
    }

    int diff= code ^ mPrevState;
    mPrevState= code;
    for( int kc= KeyEvent.KEYCODE_DPAD_UP ; diff != 0 ; diff>>= 1, code>>= 1, kc++ ){
        if( (diff & 1) != 0 ){
            // 代わりのキーコードを発生させる
            sendKey( kc, (code & 1) != 0 ? SENDKEY_DOWN : SENDKEY_UP );
        }
    }


    // アナログ値の受け取り
    float lx= event.getAxisValue( MotionEvent.AXIS_X );
    float ly= event.getAxisValue( MotionEvent.AXIS_Y );
    float rx= event.getAxisValue( MotionEvent.AXIS_Z );
    float ry= event.getAxisValue( MotionEvent.AXIS_RZ );
    float tl= event.getAxisValue( MotionEvent.AXIS_LTRIGGER );
    float tr= event.getAxisValue( MotionEvent.AXIS_RTRIGGER );

    ~
}

●複数のパッドの認識

USB ハブを経由して、同時に複数のコントローラを接続することができました。
どのコントローラも上記の同じイベントを発生させます。

getDeviceId() を参照することで、どのコントローラが送ったイベントなのか
区別できるようです。

Xbox360 Pad と PS3 Pad の組み合わせは OK、PS3 Pad を同時に 2個つないでも
きちんと区別できました。バスパワーハブだったため 3個以上は試していません。

● Playstation3 Pad (PS3 Pad) の注意点

PS3 Pad はもともとワイヤレスコントローラですが、Android 3.1 の場合
USB ケーブルで繋ぎます。

 1. PS3 Pad が電源 OFF の状態を確認
 2. USB ケーブルで Android 3.1 端末に繋ぐ
 3. (PS) ボタンを押す
 4. LED 4つが点滅したままだけど問題なし。そのまま使える。

接続前に (PS) ボタンを押してしまうとペアリングしてある PS3 本体の
電源が入ってしまうので要注意です。
ワイヤレスで PS3 本体につながってしまうと USB ケーブルをつないでも
PS3 が優先され Android で認識できません。
最初の頃、遠くにある PS3 本体の電源がいつの間にか入っていて、
なかなかつながらずにはまりました。

関連エントリ
Android 3.1 と GamePad のイベントコード