ユーザーID パスワード

技術情報

  • FAQ よくある質問
  • 個人ユーザー向けサービスのお手続きについて

コード&コラム

第10回
ARゲームを作ってみよう(2)


前へ 1 |2 |3 |4 |5 次へ

Step3 可視判定とテキストの表示

1.ARテキストの読み込み
はじめにデータベースのARテキストの情報を読み込むために、CursorをARViewクラスに渡します。

GPSARAppのonCreateメソッド内のARViewの取得の内容を以下のように変更します。

		// ARViewの取得
		arView = new ARView(this, cursor);
		// 追記
		cursor.close();

次に、ARViewのコンストラクタの内容を以下のように変更します。

public ARView(Context context, Cursor cursor) {
		super(context);

		// 追記:データベースの読み込みを行う
		readTable(cursor);
	}

ARViewで実際にcursorを使用してデータを読み込むメソッドreadTableの内容は以下のようになります。

	public class ARView extends View {
	// ARテキストの情報を保持するオブジェクト
	private ArrayList<GPSData> list;

	・・・(中略)・・・

	public void readTable(Cursor cursor) {
		// データベースに保存されている
		// 全てのARテキストの情報をlistに読み込む
		if (list != null)
			list.clear();
		list = new ArrayList();

		cursor.moveToFirst();
		do {
			GPSData data = new GPSData();
			data.info = cursor.getString(0);
			data.latitude = cursor.getInt(1);
			data.longitude = cursor.getInt(2);
			list.add(data);
		} while (cursor.moveToNext());
	}
	
	class GPSData {
		public String info;
		public int latitude;
		public int longitude;
	}
}

これでARテキストの読み込みが完了しました。それでは実際にARテキストを表示する処理を作成していきましょう。

2.ARテキストの描画
ARテキストの描画は、端末の現在地、カメラの向き、カメラの画角を考慮してARテキストが画面内にどのように写るかを計算します。ARテキストが一定以上遠い場所にあったりカメラの画角の範囲外であれば描画は行いません。

カメラの画角と範囲を定数として以下のように指定します。カメラの画角については厳密には端末毎に異なりますが、今回は携帯電話で一般に用いられる60度と指定します。また、画面のサイズについては端末ごとに大きく異なるのでコンストラクタで取得するようにします。

	// カメラの画角を指定する
	private final int ANGLE = 60;
	// ARテキストの見える範囲を指定する
	// ここでは10kmほどに指定する
	private final float VIEW_LIMIT = 100000;
	// ディスプレイサイズ
	private int displayX;

	public ARView(Context context, Cursor cursor) {
		super(context);

		// データベースの読み込みを行う
		readTable(cursor);
		
		// 画面サイズの取得
		Display disp = ((WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
		displayX = disp.getWidth();
	}

それでは実際にARテキストの描画を行う処理を作成しましょう。OnDrawの内容を以下のように変更します。

	@Override
	protected void onDraw(Canvas canvas) {
		Paint paint = new Paint();
		paint.setAntiAlias(true);

		// 追記:ARテキストの描画
		for (int i = 0; i < list.size(); i++) {
			// データの読み込み
			GPSData data = list.get(i);
			String info = data.info;
			int y = data.latitude;
			int x = data.longitude;

			// ARテキストとの距離を求める
			double dx = (x - posx);
			double dy = (y - posy);
			float distance = (float) Math.sqrt(Math.pow(dy, 2)
					+ Math.pow(dx, 2));

			// ARテキストとの距離が一定以上離れていたら、処理を行わずに次のARテキストの処理を行う
			if (distance > VIEW_LIMIT) {
				continue;
			}
			// ARテキストと現在地のなす角を求めて正規化する
			double angle = Math.atan2(dy, dx);
			float degree = (float) Math.toDegrees(angle);
			degree = -degree + 90;
			if (degree < 0)
				degree = 360 + degree;

			// 端末の向きとARテキストとの角度の差を求める
			float sub = degree - direction;
			if (sub < -180.0)
				sub += 360;
			if (sub > 180.0)
				sub -= 360;

			// ARテキストが視野に存在すれば描画処理を行う
			if (Math.abs(sub) < (ANGLE / 2)) {
				// 距離によってARテキストのサイズを決める
				float textSize = 50 * (float) (VIEW_LIMIT - distance)
						/ VIEW_LIMIT;
				paint.setTextSize(textSize);

				// ARテキストの描画を描画する
				float textWidth = paint.measureText(info);
				float diff = (sub / (ANGLE / 2)) / 2;
				float left = (displayX / 2 + displayX * diff) - (textWidth / 2);
				drawBalloonText(canvas, paint, info, left, 55);

			}
		}

		// コンパスを描画する
		drawCompass(canvas, paint);
	}

	private void drawBalloonText(Canvas canvas, Paint paint, String text,
			float left, float top) {
		// 文字列の幅を取得
		float textWidth = paint.measureText(text);
		// フォント情報の取得
		FontMetrics fontMetrics = paint.getFontMetrics();

		// 文字列の5ポイント外側を囲む座標を求める
		float bLeft = left - 5;
		float bRight = left + textWidth + 5;
		float bTop = top + fontMetrics.ascent - 5;
		float bBottom = top + fontMetrics.descent + 5;

		// 吹き出しの描画
		RectF rectF = new RectF(bLeft, bTop, bRight, bBottom);
		paint.setColor(Color.LTGRAY);
		canvas.drawRoundRect(rectF, 5, 5, paint);

		// 三角形の描画
		paint.setStyle(Paint.Style.FILL_AND_STROKE);
		Path path = new Path();
		float center = left + textWidth / 2;
		float triangleSize = paint.getTextSize() / 3;
		path.moveTo(center, bBottom + triangleSize);
		path.lineTo(center - triangleSize / 2, bBottom - 1);
		path.lineTo(center + triangleSize / 2, bBottom - 1);
		path.lineTo(center, bBottom + triangleSize);
		canvas.drawPath(path, paint);

		// 文字列の描画
		paint.setColor(Color.WHITE);
		canvas.drawText(text, left, top, paint);
	}

メソッドdrawBalloonTextは表示内容をふき出しによって修飾します。実行すると下画像のようになることが確認出来ると思います。これでアプリの枠組みは完成しました。それでは最後に、新たにARテキストを登録する処理を作成しましょう。


img


第10回 ARゲームを作ってみよう(2)
 Step1 カメラ画像へのオーバーレイと方位センサー情報の取得
 Step2 位置情報の取得とデータベースの作成
 Step3 可視判定とテキストの表示
 Step4 現在位置の登録

サンプルコード

第1回 リファレンスコード(文字列編)

第2回 リファレンスコード2(グラフィックス編)

第3回 リファレンスコード3(タッチイベント編)

第4回 リファレンスコード4(チェックボックス/ラジオグループ編)

第5回 リファレンスコード5(スピナー編)

第6回 リファレンスコード6(サウンド/ムービー編)

第7回 リファレンスコード7(トースト編)

第8回 リファレンスコード8(Google Maps API利用編)

第9回 リファレンスコード9(SQLite編)

第10回 リファレンスコード10(音声認識編)

第11回 リファレンスコード11(日付/時刻ダイアログ編)

第12回 リファレンスコード12(Bluetooth編)