読者です 読者をやめる 読者になる 読者になる

ナカザンドットネット

Android Developer's memo

ZeemoteSDK利用のサンプル

Android zeemote

先週のアレ( id:Nkzn:20110116:1295186458 )のコードです。
Zeemoteから受け取った情報で、SurfaceView上のドロイド君を動かしています。

Main.java

package net.nkzn.android.zeemote.sample;

import com.zeemote.zc.Controller;
import com.zeemote.zc.event.BatteryEvent;
import com.zeemote.zc.event.ButtonEvent;
import com.zeemote.zc.event.ControllerEvent;
import com.zeemote.zc.event.DisconnectEvent;
import com.zeemote.zc.event.IButtonListener;
import com.zeemote.zc.event.IJoystickListener;
import com.zeemote.zc.event.IStatusListener;
import com.zeemote.zc.event.JoystickEvent;
import com.zeemote.zc.ui.android.ControllerAndroidUi;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

/**
 * メインのアクティビティ。
 * Zeemote JS1のイベントハンドラの役割も。
 */
public class Main extends Activity implements IStatusListener, IJoystickListener, IButtonListener{
	
	private static final int MENU_CONTROLLER = 1;
	private SurView sv;
	private Controller controller;
	private ControllerAndroidUi controllerUi;
	
    /** 
     * 一番最初に呼ばれる
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sv = new SurView(this);
        setContentView(sv); // SurfaceViewをActivityに登録
        
		//コントローラー登録・リスナ登録
		controller = new Controller(Controller.CONTROLLER_1);  
		controller.addStatusListener(this);
		controller.addButtonListener(this);
		controller.addJoystickListener(this);
		
		controllerUi = new ControllerAndroidUi(this, controller);
		
		controllerUi.startConnectionProcess(); // コントローラーと接続開始 
    }

    /**
     * めにゅーのあれ
     */
	@Override
	public boolean onCreateOptionsMenu(final Menu menu) {
		super.onCreateOptionsMenu(menu);
		
		menu.add(0, MENU_CONTROLLER, 0, "Controller");
        return true;
	}
	
	/**
	 * サンプルからコピペしてみたけどやっぱ意味ないよなあ
	 */
    @Override
    public boolean onPrepareOptionsMenu(final Menu menu) {
       super.onPrepareOptionsMenu(menu);
	   return true;
    }
   
    /**
     * めにゅーのあれ
     */
    @Override public boolean onOptionsItemSelected(final MenuItem item) {
		if(item.getItemId() != MENU_CONTROLLER) {
			return false;
		}
		
		controllerUi.showControllerMenu();

        return true;
    }
    
    /**
     * バッテリー残量とか取れるよ
     */
	@Override
	public void batteryUpdate(BatteryEvent event) {
		//なんもなし
	}

	/**
	 * ControllerAndroidUi#startConnectionProcess()のあと、
	 * 接続が確立したときに呼ばれる
	 */
	@Override
	public void connected(ControllerEvent event) {
		// なんもなし
	}

	/**
	 * 接続が切れたときに呼ばれる
	 */
	@Override
	public void disconnected(DisconnectEvent event) {
		// なんもなし
	}

	/**
	 * ジョイスティックのイベントをアレして
	 * SurfaceViewに放り込む
	 */
	@Override
	public void joystickMoved(JoystickEvent e) {
		int x = e.getScaledX(-100, 100);
		int y = e.getScaledY(-100, 100);
		//Log.d("zmtsmpl","X=" + x + ",Y=" + y);
		sv.setX(x);
		sv.setY(y);
	}

	/**
	 * ボタン押すイベント
	 */
	@Override
	public void buttonPressed(ButtonEvent e) {
		//String buttonName = getButtonName(e);
		//Log.d("zmtsmpl", "Pressed: "+buttonName);
	}

	/**
	 * ボタン離す
	 */
	@Override
	public void buttonReleased(ButtonEvent e) {
		//String buttonName = getButtonName(e);
		//Log.d("zmtsmpl", "Released: "+buttonName);
	}
	
	/**
	 * ボタンIDから名前を作成
	 * @param event
	 * @return
	 */
    protected String getButtonName(ButtonEvent event) {
		int b = event.getButtonID();
		int gameAction = event.getButtonGameAction();			
		String label = event.getController().getConfiguration().getButtonLabel(b);
		
		String text = "button id=" + b + ",label=" + label + ",action=";
		
		switch (gameAction) {
		case Controller.GAME_FIRE:
			return text + "GAME_FIRE";
		case Controller.GAME_UP:
			return text + "GAME_UP";
		case Controller.GAME_DOWN:
			return text + "GAME_DOWN";
		case Controller.GAME_LEFT:
			return text + "GAME_LEFT";
		case Controller.GAME_RIGHT:
			return text + "GAME_RIGHT";
		case Controller.GAME_A:
			return text + "GAME_A";
		case Controller.GAME_B:
			return text + "GAME_B";
		case Controller.GAME_C:
			return text + "GAME_C";
		case Controller.GAME_D:
			return text + "GAME_D";
		default:
			return text + "GAME_UNKNOWN";
		}
	}
}

SurView.java

package net.nkzn.android.zeemote.sample;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceView;

/**
 * xとyで指定された位置にドロイド君を描画する
 */
public class SurView extends SurfaceView implements Runnable {
	/**
	 * x座標
	 */
	private int x = 0;
	
	/**
	 * y座標
	 */
	private int y = 0;
	
	/**
	 * ドロイド君格納用
	 */
	private Bitmap bitmap;
	
	/**
	 * ドロイド君の座標
	 */
	private int left=0,top=0;
	
	/**
	 * 文字描画用
	 */
	Paint paint = new Paint();
	
	/**
	 * 文字の座標
	 */
	int tx, ty;
	
	/**
	 * fps算出用
	 */
	long time = 0;
	
	/**
	 * めいんるーぷ
	 */
	Thread mainLoop;

	
	/**
	 * もろもろの値の初期化
	 * @param context
	 */
	public SurView(Context context) {
		super(context);
		bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.droid);
		paint.setColor(Color.BLUE);
		paint.setTextSize(12);
		tx = bitmap.getWidth();
		ty = bitmap.getHeight() / 2;
		mainLoop = new Thread(this);
		mainLoop.start();
	}

	@Override
	public void run() {
		while(true){
			// キャンバスをガッチリと掴む
			Canvas canvas = getHolder().lockCanvas();
			if (canvas != null) {
				canvas.drawColor(Color.WHITE);
				
				// x,y座標を取得して、ドロイド君を描画
				top += getY()/10; // 割る数で速度調整可。
				left += getX()/10; // 同上。
				canvas.drawBitmap(bitmap, left, top, null);
				
				// fpsを算出
				long now = System.currentTimeMillis();
				canvas.drawText("" + 1000f / (now - time) + "fps", tx, ty, paint);
				time = now;
				
				// ドロイド君の座標を描画
				canvas.drawText("left: "+left, tx, ty+14, paint);
				canvas.drawText("top: "+top, tx, ty+28, paint);
				
				// キャンバスを返却
				getHolder().unlockCanvasAndPost(canvas);
			}
		}
		
	}

	//以下、げったせった
	
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="net.nkzn.android.zeemote.sample"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" 
		android:label="@string/app_name">
        <activity android:name=".Main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

	<activity 
	android:name="com.zeemote.zc.ui.android.ControllerAndroidUi$Activity" />
    </application>
    <uses-sdk android:minSdkVersion="7" />
    
    <uses-permission android:name="android.permission.BLUETOOTH">
    </uses-permission>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN">
    </uses-permission> 

</manifest> 

キモは、以下の3行。

<activity android:name="com.zeemote.zc.ui.android.ControllerAndroidUi$Activity" />
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission> 

その他

画像

drawable/の中身。
f:id:Nkzn:20110123130840p:image
droid.png 直

ZeemoteSDKライブラリ

libs/の中身。jarにはパスを通します。

  • armeabi/
  • zc-strings-1.4.3.jar
  • ZControllerLib-android-1.4.3.jar
  • ZControllerLib-android-ui-1.4.3.jar
  • ZControllerLib-common-1.4.3.jar

今後の展望

特に考えてなかったりして(;´Д`)
コントローラー2つ使ったアプリも作れるみたいなので、@あたりと今度会ったときに試してみようと思ってます。


以下、こっそりとアプリックスさんに訊いてみたらOKだったこと

  • ソース公開について
    • ライブラリ(jarファイルとかsoファイルとか)を再配布しなければ、自作のコードを公開するの自体はOK
  • Zeemoteの提供について
    • Zeemoteの勉強会を企画すれば、Zeemoteを無料でレンタルとかプレゼントとかしてもらえるかも。
    • ただし在庫の問題で2月以降。

会津か新潟あたりで勉強会開きたいですね。