2012年6月25日月曜日

[Android]回転矩形と点の当たり判定

Matrixで回転させた矩形をタッチしたかどうかを判定します。

当たり判定をチェックするには、円で計算したほうが楽です。

public boolean isPointInside(PointF point, float x, float y) {
// 標的とタッチされたポイントとの距離を計算します
    float dx = x - (point.x);
    float dy = y - (point.y);
float distance = (float) Math.sqrt(dx * dx + dy * dy);

if (distance <= curRatio * bmpWidth / 2) {
return true;
}
return false;
}

ただし、これ正方形の画像にしか使えないです。


今回は、
長方形の画像の判定をしようと思います。

回転したあとの矩形の位置から範囲を計算しようとすると、とっても複雑なのでした。

そこで矩形を回転させるのではなく、
点を矩形を回転させた分だけ移動させることによって判定します。
ということが、こちらの資料に書いてました。
この資料を元にAndroidに書いてみました。

     //ポイントが当たり判定の範囲内かを返します

        public boolean isPointInside(PointF pt) {
        boolean blRet = false;
// 表示されている画像範囲の計算
float half_w = mBitmap.getWidth() * mScale / 2;
float half_h = mBitmap.getHeight() * mScale / 2;
float left = center.x - half_w;
float right = center.x + half_w;
float top = center.y - half_h;
float bottom = center.y + half_h;
RectF rect = new RectF(left, top, right, bottom);
// (1) 矩形の中心と点の距離を計算
double l = Math.sqrt(Math.pow(pt.x - center.x, 2) + Math.pow(pt.y - center.y, 2));

// (2)矩形の中心を原点として見た相対的な点C'の座標
PointF pt2 = new PointF();
pt2.x = pt.x - center.x;
pt2.y = pt.y - center.y;
// (3)点D'と横軸のなす角r2を求める
double r1, r2;
if(pt2.x != 0) {r1 = Math.atan(pt2.y / pt2.x);}
else{r1 = Math.PI / 2;}
r2 = r1 - mAngle;
// (4)点D'の座標
PointF pt3 = new PointF();
pt3.x = (float)(l * Math.cos(r2));
pt3.y = (float)(l * Math.sin(r2));
// (5)点Dに戻す
pt3.x += center.x;
pt3.y += center.y;
// 普通の矩形と点の当たり判定
if(rect.left <= pt3.x && pt3.x <= rect.right &&
  rect.top <= pt3.y && pt3.y <= rect.bottom) {
blRet = true;
}
return blRet;
        }

こんな感じ。


2012年6月23日土曜日

[Android]Matrixで表示位置を絶対座標で指定する


Matrixで位置を移動する場合、
preTranslate()
setTranslate()
postTranslate()
を使います。

が!!!

すでに指定されていた場合、
その座標を基点にして移動します。(相対座標)

さらに、
setTranslate()を使うと、
回転やスケールもリセットされてしまうのです。


今回は、絶対座標が分かっていて、
その座標を指定する方法です。
(回転やスケールも維持したままです)

便利なAPIが用意されてなさそうなので、以下のような方法で値を指定します。

1.
matrix.getValues(values)
で値を取り出します。

2.
取り出した値に値をセットします
values[Matrix.MTRANS_X] = 移動したいx座標;
values[Matrix.MTRANS_Y] = 移動したいy座標;

3.
セットした値をmatrixに戻します
matrix.setValues(values)

2012年6月19日火曜日

[Android]ライブ壁紙をOpenGLで描画する

OpenGLでライブ壁紙を作ってみました。


参考書籍はこちらの2冊。

OpenGLで作るAndroid SDK ゲームプログラミング
第3章 パーティクルシステム



初めてのOpenGL ES
付録C ライブ壁紙でOpenGL ESを利用する
    C.1 ライブ壁紙とは?
    C.2 ライブ壁紙を作成する
        C.2.1 EngineがOSから受け取るメッセージ
    C.3 XMLの編集

「初めてのOpenGL ES」サンプルコード
http://code.google.com/p/learning-opengl-es/





画像の差替えと表示方法を調整して出来上がったのが、こちら。

こちらからダウンロードできます
Google Play「FlareLiveWallpaper」

2012年6月18日月曜日

Gesture Cameraをレビュー頂きました! by dマーケット アプリ&レビュー様

dマーケット アプリ&レビュー様にGesture Cameraのレビューを掲載して頂きました。

dマーケット アプリ&レビューは、
NTTドコモ様の運営するAndroidアプリのレビューサイトです。



2012年6月8日金曜日

[Android]多角形の当たり判定


タッチしたポイントがPathの範囲内かどうかをチェックする方法です。

矩形の場合は、
Rect().contains(x, y)を使えば判定可能です。

今回は、
三角形、台形、五角形などの多角形の範囲内かどうかをチェックします。

パラメータpointsには、各座標(x,y)の値をリストで格納しています。
パラメータpは、タッチした座標。

判定方法は、地点q→地点nの2点を結んだ線分に対して、
地点pが右にあるか左にあるかでチェックしています。

右にある( 0 < height )場合、範囲内です。
左にある( height < 0)場合、範囲外です。
線上は(0 == height)となります。

private boolean checkPoint(ArrayList<PointF> points, PointF p) {
    int point_num = points.size();
 
    for(int i=0; i < point_num; i++) {
        PointF q = points.get(i);
        PointF n = new PointF();
        int j = i + 1;
        if(j < point_num) {
            n = points.get(j);
        } else {    // 最後のpointは先頭と結ぶ
            n = points.get(0);
        }
        float height = 0;
        height = p.x * (q.y - n.y) + q.x * (n.y - p.y) + n.x * (p.y - q.y); 
        if(height < 0) {
            return false;    // 範囲外
        }
    }
    return true;
}



2012年6月7日木曜日

[Android]Canvasで文字を縁取る方法


// 縁取り色を設定
Paint paint = new Paint();
paint.setAntiAlias(true);                    // アンチエイリアス
paint.setStrokeWidth(5.0f);                // 描画の幅
paint.setColor(shadowColor);             // 縁取り色のセット
paint.setAlpha(0x77);                        // アルファ値をセット
paint.setTextSize(mTextSize);           // テキストサイズ
paint.setTextAlign(Align.LEFT);          // 左寄せ
paint.setStyle(Paint.Style.STROKE);

// 縁取りを先に描画
canvas.drawText(text, posX, posY, paint);

// 文字色の設定

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(mTextSize);
paint.setTextAlign(Align.LEFT);
paint.setStyle(Paint.Style.FILL);

// 文字を描画
canvas.drawText(text, posX, posY, paint);