スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。



iko2移植中...

タイルドマップ(TiledMap)が遅い
2D RPGなどでよく使用されるタイル化されたマップをAndroidでやろうとするとどうも遅い。
いまはタイル画像から抽出して,描画範囲内のマップを描画している。

抽出には以下の関数をしようしている。
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)

この方法だとメモリを使用しないけど,
毎回抽出して描画しているので遅いのかもしれない。

マップサイズが小さいのであればオフスクリーン画面(画像)に対して,
マップに展開した画像を生成して,そこの一部を描画すると早くなるのかもしれない。
(マップサイズに比例してメモリサイズが大きくなりますが...)


移植状況
マップ画面と戦闘画面を移植したので,それなりにゲームらしくはなってきました。

永続化処理はAndroid用に新しく作らないといけないので,
現状はセーブできない。

このため記憶を頼りにしているw処理は,ほとんど機能せず。

今月に単純移植は終えて,
来月は改めて作り直す必要がある音周りと永続化(セーブ)まわりをやっていきたいなぁ。

このアプリ自体,スマホだと見向きもされない気がするけど。。。
地道にがんばろうw
スポンサーサイト

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android その5

Enumが遅い件
いろんなサイトでJavaのenumはパフォーマンスを落とすと書かれている。

デバッグしていると(デバッガが接続しているときだけ)
なぜか処理が重くなっていた。

調査してみるとコールしてもいないenum.ordinal()が呼ばれている。

前にswicth文とenumで遅くなるという
かろうじて覚えてキーワードから検索して以下のサイトを見つけました。

http://news.mynavi.jp/column/java/015/index.html

C/C++と違って単純にjumpしているわけじゃないみたいですね。

こちらのサイトでも書かれています。
http://labs.techfirm.co.jp/android/cho/1293
http://ipa-style.blogspot.jp/2007/02/javaenumswitchswitchtable.html

逆コンパイルして検証する技術も身につけないとな...。


ということでsiwtch文をif文に置き換えました。
いくぶんか早くなりました。

enumの立場ないなw

テーマ : ゲーム開発
ジャンル : コンピュータ




Javaのファイル数をカウントする

備忘録として...

find ./path -type f -name "*.java" | wc -l

これでパス以下のjavaファイルをカウントできる。

findをそのまま実行でファイルパスが表示される。

「wc -l」で行数カウント。

移植状況をこれで把握できる〜!!

テーマ : ゲーム開発
ジャンル : コンピュータ




iko2の移植 ~ オープニングの表示 ~

テレビをつけっぱなしにしていると深夜アニメ「織田信奈の野望」やってることがあります。
このオープニングソングが頭にこびりついて,ずっと流れてました。

寺川愛美さんが歌っているそうです。
http://ameblo.jp/aimi-sound/

イケイケのハードロックにパワフルだけど可愛い声がヤバイですねw
声萌えしちゃいますw

肝心なアニメの方はまったく頭にはいらないのが残念ですけど,
この曲聴いて地道な作業も乗りきれそうですw

視聴->
http://canime.jp/cgi/page/detail/display/201200000540/001/


iko2はなんとかオープニングまで表示できました。
オープニングはセーブデータを読み込んで反映するつー意外に重い部分でした。

それに気がつかず昨日はずっとMIDPのクラスをAndroidへ移植して
移植したクラスに存在しないクラスがってエラーがでて,
そのクラスを移植すると存在しないクラスがって...

Oh!ループ。

ですが,今日はやっとビルドもとおるようになりました。
セーブデータとかは無視ってますがw

当面の目標は「セーブできないし音もでないけどゲームはできる」という状態ですw
今月中にそこまでいくかな!?

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android移植 その4

リソースの扱い
MIDPとAndroidで大きな違いはリソースの扱いが全然違うということ。

MIDPはjarにパッケージ化したときはルートフォルダに全部展開され,
getClass().getResourceAsStream("パス")で取得できました。

Androidではリソースのファイルタイプ毎にフォルダが階層されていて,
リソースのタイプごとに異なるメソッドでアクセスする。

例えばtxtファイルのような生データのときは以下のメソッドでInputStreamを取得します。
Resources.openRawResource()

これで困ったことが,txtファイル内に次のリソース名(例えば a.txtの中にb.txtって書いてあるとき)が書いてあるとき,
MIDPでは読み込んだ文字列をそのままパスとして使えました。

AndroidではリソースIDに置き換える必要があり,
単純にパスを渡すだけでは取得できません。

そういうときは以下のメソッドでIDを取得するそうです。
Resources. getIdentifier()

ふむ...一手間かかるね〜。


enumの扱いにまだ迷う
連番振るの面倒なのと,人間が手で振ってたら間違った値を振ってしまうので
前作ではプリプロセッサを使用してenumを強引にしようしてました。
(J2MEではenumはサポートしていない)

AndroidではJava5SEベースになったのでenumがサポートされたので置き換えてみようと思ったのですが...。

enumのメンバは配列のインデックスに直接使えないんですよね。
ordinal()メソッドを呼んで強引に使ってますが...。

それにenumはオブジェクトだからnull値もありえるということで,
チェックの方法も変わってくるし...。

前回も書いたようにJavaでは初期値を与えることができないので,
-1から始めるenumを作れないのも難点。

かといって160個くらいの要素を持つenumを
全部static fianl intに置き換えるのも...。

Javaではenumを使ったときは配列を使うのではなくて
連想配列のようなもので対応しろってことなのだろう。

ふむ〜今日は疲れモードで愚痴りました。
それではまた明日〜w

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android移植 その3

リソースの取得方法
MIDPではリソースの取得はClass.getResourceAsStream()から取得することができました。
Classはどのクラスでもよいので,いつでもどこでもコールすることができたのですが,

AndroidではResourcesクラスからresフォルダ, assetsフォルダへアクセスすることができます。
しかしResourcesクラスは取得場所が限られる。

大体の場合はActivityクラス内で取得していると思う。
このため,MIDPのように「いつでもどこでも」取得するということができない。

Resourcesクラスをいつでもどこでもアクセスできるようにする仕組みを実装する必要がありそうだ。

Resources.getSystem()はstaticメソッドでResourcesインスタンスを取得できる。
http://developer.android.com/intl/ja/reference/android/content/res/Resources.html#getSystem()

ただし説明にも書かれているようにシステムで共有しているインスタンスであり,
アプリケーションのリソースではないようです。

テーマ : ゲーム開発
ジャンル : コンピュータ




タイトル画面が表示できた〜

やっとタイトル画面を表示することができたよ〜。
やた〜!!

Androidでも同じ画面が表示されると,うれしいもんだねぇ涙

まだまだやることもあるだろうけど,
ひとまず安心。

そして昨日まで調査していたGraphics.drawRegion()の移植はやめました。
AndroidのMatrixの中身は問題なく設定されているけど,
こちらが考えているような結果にならないので...。

Matrixの使い方をもっと深く調査していく必要がありそうだ。

回転して一部画像を抽出する処理は
いまのところMIDPのSpriteクラスのみなので,
Spriteクラス側で問題を吸収しようと考えています。

また明日も引き続き移植だ〜!!

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android移植 Graphics.drawRegion()...

MIDP GraphicsクラスのdrawRegion()メソッドの移植していたのですが,
これが...。

なにが問題かといえば,元画像の一部を抽出して,
その抽出した画像を回転・反転させるという。

AndroidのCanvasクラスには回転や反転させて描画させるメソッドがあります。
void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

また一部を抽出するメソッドもあります。
void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)

ですが...
一部を抽出して,そこに回転や反転を反映させるメソッドはありません。

drawRegion()メソッドは描画メソッドなので,
30FPSで作られたゲームでは1秒間に30回コールされます。

もしこの中でBitmapインスタンスを生成していたら
たまったものじゃない...と勝手に想像しています。
(実際にパフォーマンスをはかった訳じゃないので希有なのかもしれない)

なので,できるだけインスタンスを生成しないで描画する処理を考えていました。
下記の抽出して回転を加えた処理では,以下のことを想定して実装しました。

1.Canvasに対してMatrixを設定する。
2.drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)で抽出する。
このとき1.で設定したMatrixが適用される。

一見,うまくいったように見えるけど,Y軸がなぜか-145pxのオフセットがかかっている。
自分の考えが何か間違っているのだと思うけど...。

明日は,drawRegionメソッドの移植をやめて,
コール側で一時的な画像を生成して描画するように
実装しなおす方策にしようかと思う。

下記にコードを添付します。
もしわかる方がいれば教えてください。


matrixtest.jpg
package com.example.bitmap.matrix.test;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

public class MainActivity extends GraphicsActivity
{
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(new ScreenView(getApplicationContext()));
	}

	private static class ScreenView extends View
	{
		// 転送元Bitmap
		private Bitmap mSrcBitmap = null;

		// 描画用
		private Paint mPaint = null;

		//
		private Matrix mMatrix = new Matrix();

		// / 幅
		static final private float WIDTH = 100f;

		// / 高さ
		static final private float HEIGHT = 100f;

		/**
		 * コンストラクタ
		 * 
		 * @param context
		 */
		public ScreenView(Context context)
		{
			super(context);

			mSrcBitmap = Bitmap.createBitmap((int) WIDTH, (int) HEIGHT, Bitmap.Config.ARGB_8888);

			Canvas canvas = new Canvas(mSrcBitmap);

			canvas.drawColor(Color.BLACK);

			Path path = new Path();

			// (50, 50)を中心に半径30の円を書く
			path.addCircle(WIDTH / 2, HEIGHT / 2, 30.0f, Path.Direction.CCW);

			Paint paint = new Paint();
			paint.setAntiAlias(true);
			paint.setFilterBitmap(true);
			paint.setStrokeWidth(6);
			paint.setColor(Color.BLUE);

			canvas.drawPath(path, paint);

			final float pointY1 = 10f;
			final float pointY2 = HEIGHT - pointY1;
			final float pointX1 = 10f;
			final float pointX2 = WIDTH - pointX1;

			path.reset();
			path.moveTo(WIDTH / 2, pointY1);
			path.lineTo(pointX2, pointY2);
			path.lineTo(WIDTH / 2, pointY2);
			path.close();

			paint.setStyle(Paint.Style.FILL);
			paint.setColor(Color.GREEN);
			canvas.drawPath(path, paint);

			path.reset();
			path.moveTo(WIDTH / 2, pointY1);
			path.lineTo(pointX2, pointY2);
			path.lineTo(pointX1, pointY2);
			// path.lineTo(50f, 10f); // lineTo()だと線を閉じたことになっていなかった
			path.close();

			paint.setStyle(Paint.Style.STROKE);
			// paint.setStrokeCap(Cap.SQUARE);
			paint.setColor(Color.RED);
			canvas.drawPath(path, paint);

			mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
		}

		/*
		 * (非 Javadoc)
		 * 
		 * @see android.view.View#onDraw(android.graphics.Canvas)
		 */
		@Override
		protected void onDraw(Canvas canvas)
		{
			canvas.drawColor(Color.WHITE);

			canvas.save();
			canvas.translate(10.0f, 10f);
			canvas.drawBitmap(mSrcBitmap, 0.0f, 0.0f, mPaint);

			mMatrix.reset();
			mMatrix.setRotate(90f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate(WIDTH + 10f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);

			mMatrix.reset();
			mMatrix.setRotate(180f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate((WIDTH + 10f) * 2f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);

			mMatrix.reset();
			mMatrix.setRotate(270f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate((WIDTH + 10f) * 3f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);
			canvas.restore();

			// ---------------
			// 左右反転と回転
			// ---------------

			canvas.save();
			canvas.translate(10.0f, HEIGHT + 20f);
			mMatrix.reset();
			// mMatrix.setScale(-1f, 1f); // 左右反転
			// (0,0)を軸に反転するので反転後は-WIDTH方向に画像が展開される
			// mMatrix.postTranslate(WIDTH, 0f);
			mMatrix.setScale(-1f, 1f, WIDTH / 2, HEIGHT / 2); // 左右反転(画像の中心を軸に)
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);

			mMatrix.reset();
			mMatrix.setScale(-1f, 1f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postRotate(90f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate(WIDTH + 10f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);

			mMatrix.reset();
			mMatrix.setScale(-1f, 1f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postRotate(180f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate((WIDTH + 10f) * 2f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);

			mMatrix.reset();
			mMatrix.setScale(-1f, 1f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postRotate(270f, WIDTH / 2, HEIGHT / 2);
			mMatrix.postTranslate((WIDTH + 10f) * 3f, 0f);
			canvas.drawBitmap(mSrcBitmap, mMatrix, mPaint);
			canvas.restore();

			// ----------
			// 一部抽出
			// ----------

			float offsetY = (HEIGHT + 10f) * 2f + 10f;
			float offsetX = 10f;

			canvas.save();

			final int left = (int) (WIDTH / 4f + 0.5f);
			final int top = (int) (HEIGHT / 4 + 0.5f);
			final int width = (int) (WIDTH / 2 + 0.5f);
			final int height = (int) (HEIGHT / 2 + 0.5f);

			Rect src = new Rect(left, top, left + width, top + height);
			RectF dst = new RectF(left, top, left + width, top + height);

			{
				RectF dst2 = new RectF(dst);
				dst2.offset(offsetX, offsetY);
				canvas.drawBitmap(mSrcBitmap, src, dst2, mPaint);
			}

			canvas.restore();

			canvas.save();
			offsetX += WIDTH + 10f;
			mMatrix.reset();
			mMatrix.setRotate(90f, WIDTH / 2f, HEIGHT / 2f);
			mMatrix.postTranslate(offsetX, offsetY + 145f);	// なぜか145f
			canvas.setMatrix(mMatrix);
			canvas.drawBitmap(mSrcBitmap, src, dst, mPaint);
			canvas.restore();

			canvas.save();
			offsetX += WIDTH + 10f;
			mMatrix.reset();
			mMatrix.setRotate(180f, WIDTH / 2f, HEIGHT / 2f);
			mMatrix.postTranslate(offsetX, offsetY + 145f);	// なぜか145f
			canvas.setMatrix(mMatrix);
			canvas.drawBitmap(mSrcBitmap, src, dst, mPaint);
			canvas.restore();

			canvas.save();
			offsetX += WIDTH + 10f;
			mMatrix.reset();
			mMatrix.setRotate(270f, WIDTH / 2f, HEIGHT / 2f);
			mMatrix.postTranslate(offsetX, offsetY + 145f);	// なぜか145f
			canvas.setMatrix(mMatrix);
			canvas.drawBitmap(mSrcBitmap, src, dst, mPaint);
			canvas.restore();

			// ---------------------
			// 左右反転して一部抽出
			// ---------------------
		}
	}
}

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android 移植 その2

JavaのEnumが使いにくい

JavaのEnumは初期値を設定することができません。

代替案としてenumにintのメンバ変数を持たせて,
コンストラクタで値を指定するのは...というものがありました。
それじゃ〜static final intで値降っているのとかわらないじゃん><

初期値を持たせることができれば

enum Index
{
    INVALID_INDEX = -1,
    FIRST_INDEX,
    MAX
}

って、できるのにな...。


VectorなどのCollectionの扱いがかわっている
MIDPでVectorなどで要素を全部まわすときはEnumaretionクラスを取得して回していたが,
AndroidはJava5ベースなのでEnumaraiton<?>のようなジェネリクスクラスになっている。
ただJava5ではiterator()メソッドを使う方がいいって...どこかに書いてあったような。
そもそもVectorクラス自体が互換性のために残されたクラスでArrayListクラスを使った方がいいなんて...
J2MEとJ2SEのフラグメント問題とMIDPとAndroidのフレームワークの差...両方吸収って><

テーマ : ゲーム開発
ジャンル : コンピュータ




MIDP -> Android移植

MIDPをAndroidへ移植中です。

ソフトウェアボタンはどう扱う?
ソフトウェアボタンはCommand, CommandListenerで構成されています。
Androidでは仮想ボタン(画面上にボタンを表示する)方法をとっているので,
ボタンの追加や削除も自前でやる必要があります。

MIDPのときはキーをリスニングするスレッドがボタンのイベントを拾って,
CommandListenerインターフェースを実装したクラスへ伝播させるという方法をとっています。

自前で仮想ボタンを作ったのでキーイベントの処理は十字キーと一緒にしたので,
キーの状態を管理するクラスがソフトウェアボタンの押下状態も持つようになった。

このためイベントの発生タイミングはマルチスレッドではなくなったので,
そのあたりの実装をどうやってかえるか...。

今後の移植はないので,Androidに特化した形に移植すればいいのですが。
移植する作品がおおい会社では抽象化して,さらにソフトウェアボタンも十字キーとは
異なるイベントの伝播する...というところまでエミューレートした方がいいんでしょうね。


画像の扱い
MIDPではImageクラスが画像を扱うクラスでしたが,
AndroidではBitmapクラスになっています。

このあたりも抽象化した方がいいんだろうとは思っているが...忘れてたw

このあたりどーしようかな...。

リソースからの読み込み処理部分がかなり違うとは思っているけれど...。


まずはタイトル画面だけを表示したいなぁ。
がんばんべ〜。

テーマ : ゲーム開発
ジャンル : コンピュータ




iko2のソースを入れてみる

MIDPのGraphicsとFontの互換クラスを実装したので,
iko2のソースコードを入れてみた。

やはり他のクラスを参照しまくりなので,エラーばかり。
これからは,ひとつずつ自前のクラスを移植していって
エラーをつぶす作業。

大体1〜2週間かかるだろうか。
その間は試験的に動かして〜なんてできないので,辛抱ですね。

MIDPクラスの移植忘れがあった。
Displayableクラスで,使用目的はソフトウェアボタンの追加と削除。
今回は自前でボタンを用意しているので,そもそも必要はないが,
ボタンのラベル名の変更だけは必要。

地道にがんばるべ〜!!

P.S.
「新!あげぱん探偵ヒラメキVOL1」を昨日なんとかクリア。
ノーマルクリアだったのだけど...ハッピーエンディングってどうやるんだろう...。

あのゲームはつくづくタッチパネル向きのゲームだなと思いました。

テーマ : ゲーム開発
ジャンル : コンピュータ




Grapicsクラスのクリッピング処理の移植

MIDPのGraphicsクラスにはいくつかのクリッピング処理があります。

Graphics.clipRect()

まずはGraphics.clipRect()を実装する。
androidのCanvasクラスにも同じメソッドが存在する。

http://developer.android.com/intl/ja/reference/android/graphics/Canvas.html#clipRect(int, int, int, int)

MIDPのものと違う点は,引数の値がright, bottomになっていることくらい。
リファレンスに書いてあるとおり,

Intersect the current clip with the specified rectangle, which is expressed in local coordinates.

現在のクリップと交差する場所が有効範囲になります。
MIDPでも同じ使用なので特に問題なく移植できそう。

androidでのクリッピング処理については下記サイトがわかりやすいと思います。

http://ichitcltk.hustle.ne.jp/gudon/modules/pico_rd/index.php?content_id=84

リファレンスには正式に書いていないが言葉の意味からRegion.Op.INTERSECTでクリップしていると判断できるでしょう。

http://developer.android.com/intl/ja/reference/android/graphics/Region.Op.html

公式リファレンス...ちゃんと説明かけや。



Graphics.setClip()
clipRect()と違ってCanvasクラスにはsetClipは存在しない。
しかし以下のメソッドで代用することができる。

public boolean clipRect (float left, float top, float right, float bottom, Region.Op op)

Region.Op. REPLACEを指定すれば新しいクリッピング領域を設定することができる。
このため上記メソッドをラッピングすれば,setClip()を移植することができる。


Graphics.getClipWidth(), getClipHeight()
Canvasクラスにはクリッピングの幅や高さを直接取得するメソッドはない。
しかしgetClipBounds()があるので,ここから高さと幅を取得することができる。

これはGraphics. getClipX(), getClipY()にも適用できる。

ということでMIDPのGraphicsクラスの互換実装は,これにて終了!!
パチパチ!!

テーマ : ゲーム開発
ジャンル : コンピュータ




drawLineの移植

MIDPのGraphics.drawLineの移植。

MIDPには2つの線種しかない。

・直線 (SOLID)
・破線 (DOTTED)

破線をAndroidで実現するには,
DashPathEffectを利用する。

このクラスで破線の間隔を設定する。

http://developer.android.com/intl/ja/reference/android/graphics/DashPathEffect.html

コンストラクタは以下のとおり。

DashPathEffect(float[] intervals, float phase)

第一引数に間隔,第二引数に開始位置を設定する。
第一引数の配列の要素は常に2の倍数でないといけない。

これは破線の幅と空間の幅が1つの組になっているから。
Androidのサンプルにもあったが,phaseの値を描画のたびに更新すると
線がアニメーションしているように見える。

大抵のときは第二引数は0で問題ないでしょう。

DashPathEffectインスタンスをPaint.setPathEffect()に設定すればOK。
あとはPaintの線の幅や線のスタイル(Paint.Style.STROKE)を設定して終わり。


drawText()のY軸のアンカーポイントの謎

drawLine()の移植が終わった後に,
drawText()の表示位置について調査。

MIDPではデフォルトでLEFT, TOPをアンカーに文字列が表示されていたいのですが,
AndroidではLEFT,BOTTOM(またはBASELINE?)で表示される。

こっちのが世の中標準の考え方なのかな...。


DisplayMetricsのdensityDpiの謎
DisplayMetricsでディスプレイの状態を取得することができるのだけど,
densityDpiの値は仮想な値が入っている。

自分が実機デバッグしている端末は106SHなんだけど
321dpiなんだけど,densityDpiの値は320。

この値について検索して調べてみると,実際のdpiではなくて
デフォルトの160dpiの倍数に丸められているように見える。

この値をもとに対応するリソースフォルダ(drawable-ldpiとか)を選択するということだろうか。
リファレンスみても詳しい説明がのっていない。

今回は画面サイズを特定しているからいいけど,
いろんな解像度とDPIに対応させる方法がまだわからない。

とくにアスペクト比の違いってどうやって吸収しているのだろうか...。


drawBitmapの謎
BitmapFactoryでResourcesクラスを渡すと,スクリーンのdensityDpiにあわせて
画像を拡大・縮小して読み込んでくれます。

drawBitmapに渡す座標は生の座標になるので,
画像はスケーリングされているが,座標は自前でスケーリングしないといけない。

なんかこれって変だよな...。


いろいろ疑問は残しつつ,
移植の作業を優先して進めてます> <

テーマ : ゲーム開発
ジャンル : コンピュータ




BitmapDrawableと同じようにアンチエイリアスがかかったBitmapを描画する方法

Bitmapを描画してもアンチエイリアスが効いていない。

Canvas.drawBitmap()にはPaintクラスを引数に設定できるので,
Paint.ANTI_ALIAS_FLAGを設定したが,それでも駄目でした。

http://blog.svartalfheim.jp/?p=380

こちらに書かれているようにBitmapDrawableを使用すると
アンチエイリアスが効いていた。

BitmapFactory.OptionsにはinDitherフィールドがあります。
このメンバ変数をtrueにしてみたけど,やはり駄目。

もう少し調べてみると以下の情報が...。

http://stackoverflow.com/questions/2183808/android-bitmapfactory-decodebytearray-gives-pixelated-bitmap

ここに書かれていることは今回の話とは関係ありませんが,
PaintクラスのコンストラクタにPaint.FILTER_BITMAP_FLAGを設定して生成したところ,
BitmapDrawableと同じ描画になりました。

ただ記事に紹介されているように
BitmapFactory.OptionsのinDitherが設定されていなくても有効になりました...う〜ん。

http://developer.android.com/intl/ja/reference/android/graphics/BitmapFactory.Options.html#inDither

Paint.FILTER_BITMAP_FLAG
http://developer.android.com/intl/ja/reference/android/graphics/Paint.html#FILTER_BITMAP_FLAG

リファレンスみても読み取れないよ> <

Paintの値はNDK側で使用されているようなので,
Javaのソースコードで読めない。

結局,何がおきているか調べるにはネイティブ側のソースみないとってことだろうか。

テーマ : ゲーム開発
ジャンル : コンピュータ




Graphics.drawImage()の移植 その2

昨日に引き続きMIDPのGraphics.drawImage()の移植。

昨日問題になっていたのは,
「Canvas.drawBitmap()を実行するとBitmapが2倍に表示されてしまう」
というもの。

なぜ2倍に表示されてしまうかについては,
フレームワーク側の見えない処理で悩ましい問題でした。

結果から言うと,
(NDKのソースまではみていないですが...)

1. 転送元のBitmapと転送先のBitmapのdensityの値で拡大縮小処理を実行する。
2. Canvas.scale()に設定した倍率で拡大・縮小される。

ということがわかりました。


BitmapFactory.decodeResource()のResourceを引数にとる方は,
画面のDPIからdensityを設定し,読み込むときはデフォルトの160DPIから換算した大きさに変換します。

どいうことかというと,
今回テストで読み込んだ画像はW240 x H90(いずれもpx)だったのですが,
BitmapFactoryでBitmapを読み込んだところ
W480 x H180になっていました。

これは実行した端末のDPIが320で,デフォルト160の2倍の密度だったため,
自動的に2倍にして読み込まれたということになります。

またBitmapに設定されたdensityは320が設定されます。


このとき描画先のCanvasが320DPIでdensityが設定されているとき,
描画するBitmapのdensityと同じなので,
拡大・縮小処理されずに等倍で描画されます。

しかし,ここでCanvas.scale()が2.0で設定されているとき,
Bitmapはscaleの値によって2倍に描画されてしまいます。


ではscaleを1.0に設定すればいいのでは?
と考えられますが,文字列や座標などdensityを持たないものは
densityによる拡大・縮小がおこわなわれません。

そのためPaint.setTextSize()で12を設定してCanvas.drawText()を実行すると
そのままの大きさで表示されてしまいます。


これでは画面密度ごとに同じサイズで描画することができません。
(px指定したものと同じで,dp指定とは違う)

Canvas.scale()で画面密度に対応する倍率を設定しておけば,
Paint.setTextSize()を指定するコードはそのままに,
勝手に画面に対応した大きさへ拡大・縮小してくれます。
(いわゆるdpで設定したときと同じ効果)


Canvas.scale()を共通した値のままBitmapを描画する

最初に述べたように,

1. 転送元のBitmapと転送先のBitmap(Canvas)のdensityの値で拡大縮小処理を実行する。
2. Canvas.scale()に設定した倍率で拡大・縮小される。

であるから,Bitmapのdensityによる拡大・縮小を実行せず,
すべてCanvas.scale()に設定したスケール処理に任せればよい
ということになります。

そうするには転送元と転送先のdensityの値を同じにする必要があります。
BitmapFactoryでDPIによって拡大した画像が生成されてしまうことを考えると
その分のメモリがもったいないので,実寸大の大きさでBitmapを読み込むことがよいのでは...
と考えました。

それにはBitmapFactory.Optionsを使いBitmapを生成します。

BitmapFactory.OptionsのinScaledをfalseに設定すれば
原寸大の大きさで画像を生成してくれます。
(逆にtrueにしたときディスプレイのDPIで拡大・縮小した画像を生成してくれます)

こうしてできたBitmapは160DPIなので,
転送先が160DPIであればdensityによる拡大・縮小は行われず,
scale()による拡大・縮小だけが行われます。


テストしてわかったことですが,
描画先が160DPIでBitmapが320DPI, Canvas.scale()には2.0を設定したとき,
densityによる縮小処理が実行され,
その後scale()によって拡大されているので,
Bitmapが160DPIのときに比べて画質が粗くなっていました。


ここから先,処理を追うにはC言語で書かれたnative側をみる必要があります。
C言語も読めるのですが,多分ボリュームが多いので読んでる時間を考えると...。

リファレンスを読むより確実なんだけどね。

いまは移植作業を優先だな。

テーマ : ゲーム開発
ジャンル : コンピュータ




Graphics.drawImage()の移植

今日はGraphics.drawImage()の移植しています。
画像描画はよくやることなので,しっかり実装していきたいな。

Canvasクラス内で画像を描画するメソッドを探したところ,
多分drawBitmapがそれにあたると。

計7コありますねw

今回はリソースフォルダに置いたpngファイルから読み込むということで,
Bitmapクラスを使用した描画関数を使用していくと思います。

BitmapファイルはBitmapFactoryクラスから生成することができる。

http://developer.android.com/intl/ja/reference/android/graphics/BitmapFactory.html#decodeResource(android.content.res.Resources, int)

Imageクラスの代わりがBitmapクラスになるでしょうwww

public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)

の4つになります。
Matrixを引数に持つメソッドは回転や縮小などの変形しながらの描画で,今回にはあてはまらず。
Rectを引数に持つクラスは,拡大・縮小をして描画するときのケースなので,今回にはあてはまらず。

となるとfloatを引数に持つメソッドだな...
とリファレンスを読むと...。

Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, transformed by the current matrix.

現在のMatrixによって変形されます...ってオイ。
CanvasクラスにはsetMatrixメソッドが用意されいていて,
この値が反映されてしまうようですね。

全体が変形しているときはそれにあわせるということでしょう。
移植時は変形なんて使わないからサー,ここは無視するか...。

もし心配であれば現在のMatrixを取得して,描画後に戻してあげるという作業が必要になるでしょう。

で実際に描画したら...。
Canvas.scaleに設定した倍率が影響されていました。
フォントのときはこの値を設定していないと,画面のdpiにあわせたサイズ(dip, dp)にならなかったのですが...。

また画像が汚い...。
あるサイトを発見。

http://blog.svartalfheim.jp/?p=380

今日中に終わらせようとしたけど...,
BitmapFactoryで画像がDPIに従って拡大・縮小されて読まれるが,
座標系は拡大されないことがわかった。

Canvas.scale()メソッドで設定した値が画像に対しても有効か,
どういうケースで有効かはまた次回以降に持ち越し...。



・番外

drawBitmapMeshってなに???
http://sakef.jp/blog/2011/02/android04_image_translation/

ん~無視w
いずれやります,きっとw

テーマ : ゲーム開発
ジャンル : コンピュータ




SurfaceViewのCanvasを初期化する

SurfaceViewの画面を描画するとき,フレーム毎に初期化する必要がありました。

いままではSurfaceHolderからCanvasを取得して
Canvasの大きさ分drawRect()していました。
(このとき使用するPaintはFILLモードで)

しかしCanvasには便利なメソッドが用意されているじゃないですか...。

http://developer.android.com/intl/ja/guide/topics/graphics/2d-graphics.html#on-surfaceview

ここに書いてあったのですがCanvasクラスのdrawColorメソッドで初期化できるようです。

ただリファレンスの内容をみると???なことが。

http://developer.android.com/intl/ja/reference/android/graphics/Canvas.html#drawColor(int)

Fill the entire canvas' bitmap (restricted to the current clip) with the specified color, using srcover porterduff mode.

指定した色でCanvasクラス内のbitmapを塗りつぶすよ。
そのときは現在のクリップが反映(で制限)されるよ。
使われるのはsrcover porteduff mode...って何!?

Src Over PortDuff Modeらしい。

PortDuffは...

http://developer.android.com/intl/ja/reference/android/graphics/PorterDuff.Mode.html

リファレンスにありましたが説明がほとんどない。
概念的にはJavaのAlphaCompositeクラスと同じようです。

http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/awt/AlphaComposite.html

PorterさんとDuffさんが書いた論文(?)のようです。
この論文に従って実装されたものがJavaのAlphaCompositeクラスで,
AndroidのPorterDuff.Mode列挙型のようです。

2つの色を合成するときの合成処理方法についてのモードということでしょうか。

その処理について説明されているページがいくつか...

PortDuff.Modeについての説明
http://d.hatena.ne.jp/Superdry/20110204/1296809054

http://www.ccad.sist.chukyo-u.ac.jp/~mito/ss/program/Java/AppletApp/graph/transprcy/index.htm
http://www.ibm.com/developerworks/jp/java/library/j-mer0918/

PortDuff.Mode列挙型についての説明
http://lovely.na.coocan.jp/wiki/index.php?Android%2FPorterDuff

ふ~詰め込むこといっぱいあり過ぎだな。



くぼたまアプリさんの新作

昨日寝る前にGoogle Playをのぞいていたら
くぼたまアプリさんの新作が配信されていた!!

https://play.google.com/store/apps/details?id=jp.kubotama.agepan_new1s

眠い目をこすりながら,さっそくプレイ!!

やばいクオリティ高い!!
スマホのスペックが高くなったことで
携帯のときよりもさらにクオリティがあがっています。

またタッチパネルでの操作主体に変更されたので,
操作性も格段に向上している。

まだ序盤やりはじめたところですが,
いろいろと見習うところありますね~。

疑問なのは,複数の解像度にどうやって対応しているのかつー。
解像度(dpi)ごとのリソース用意しているのかな...。

アスペクト比が違うものに対して,どうアプローチしているのか...。

いろいろ疑問がわいてくる。

はやく移植終わらしてスマホに特化したアプリ作りたいな。



移植作業中...

iko2のコードを移す前段階で,今日はMIDPのGraphicsクラスと互換を持つクラスを作ってました。
drawChar()メソッドを移植していました。

このメソッド自体は移植できたのですが,
根本的なフォントサイズの問題が解消されていない。

フォントサイズの検証をしたが,フォントの高さを縮小するようなメソッドはなく,
幅を拡大するものだけだった。

実際に12 x 12になるようにしてみたんだけど...。
めっちゃださい。

せっかく奇麗なフォントがブサイクになってしまったので,
拡大・縮小してフィットさせる方法は中止。

このためフォントの高さを12とするか,幅を12にするか...。

今回調べた範囲ではフォントの幅より高さの方が大きいことがわかったので,
フォントの高さを12にするような仕組みをいれていこうと思う。

大は小をかねるということで...。



Paint.setTextSize()の謎

Paint.setTextSize()に12を指定してFontMetricsIntを取得した結果は以下のようになった。

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(12);
paint.setColor(Color.WHITE);

// 結果
FontMetricsInt top              : -13
FontMetricsInt bottom           :   4
FontMetricsInt accent           : -11
FontMetricsInt descent          :   3
FontMetricsInt bottom - top     :  17
FontMetricsInt descent - accent :  14

FontMetrics top              : -12.574219
FontMetrics bottom           :  3.5859375
FontMetrics accent           : -10.675781
FontMetrics descent          :  3.3046875
FontMetrics bottom - top     :  16.160156
FontMetrics descent - accent :  13.980469

12を設定しても,テキストのサイズがpx単位で12になる箇所がない。
setTextSizeの引数はなんの単位なのだろうか???

もしかするとspなのかもしれないと思い
システムのフォントサイズを変更しても上記の値はかわらなかった。

システムのフォントを「モリサワ新ゴM」から「LC明朝」へ変更したら以下のようになった。

FontMetricsInt accent           : -11
FontMetricsInt descent          :   1
FontMetricsInt bottom - top     :  13
FontMetricsInt descent - accent :  12
FontMetrics top                 : -10.558594
FontMetrics bottom              :   1.359375
FontMetrics accent              : -10.558594
FontMetrics descent             :  1.4414063
FontMetrics bottom - top        :  11.917969
FontMetrics descent - accent    :  12.0

「LC明朝」では指定した12と一致したピクセルの高さになった。
フォントによってピクセル数が違うということがわかったはいいが,
以前setTextSizeに指定する値が何を表しているのか...。

まさか横幅!?

final float halfSize = paint.measureText("A");
final float size = paint.measureText("あ");

//結果「モリサワ新ゴM」
Font width. A:7.296875, あ:12.0

//結果「LC明朝」
Font width. A:7.296875, あ:12.0

//結果「SHクリスタルタッチ」
Font width. A:7.296875, あ:11.984375

//結果「Roboto Regular」
Font width. A:8.0, あ:12.0

SHクリスタルタッチもほぼ12。
他のフォントもほぼ12。

他の端末でもフォントの幅が12に近い値であれば,
幅の可能性が高いね。

ちなみにandroidのソースをみると

public native void setTextSize(float textSize);

nativeメソッドでした。

もし幅であわせて高さであわせないというならば,
以下のサイトのようにフォントをストレッチして12 x 12にフィットさせるしかなさそう。

http://wiki.livedoor.jp/moonlight_aska/d/%A5%C6%A5%AD%A5%B9%A5%C8%A5%B5%A5%A4%A5%BA%A4%F2%A4%AB%A4%A8%A4%EB

全角で12となると英語圏の人はどうなるのだろうか???
半角しかない世界では12の扱いって???

リファレンスに書かれていない以上,どうしようもない。



文字列の正確な値はどうやって決めればいいのか...

文字列を描画するときにテキストのサイズを指定することができる。

http://developer.android.com/intl/ja/reference/android/graphics/Paint.html#setTextSize(float)

Paint.setTextSize()。
これに指定する値の単位がなんなのかわからない。
ピクセル?それともポイント?DP?

リファレンスにも書いてないので困りました。

FontMetricsでサイズを計算しても,指定したサイズより大きいものになっている。

携帯電話時代はビットマップフォントだったので常に12px x 12 pxと決まってたのだが。
できればこのサイズで表示したい。

もう少しの研究が必要みたい。



.gitignoreに設定しても無視されない

自分用にメモ。

.gitigonreに書いたファイル、フォルダが無視されない。

どうやら既にコミットされているものは無視されないようです。

http://blog.9wick.com/2012/08/gitignore-file/

そのためgitコマンドを使用してリポジトリから削除します。

git rm -cached ファイル名

http://transitive.info/article/git/command/rm/

git rm -cached --ignore-unmatch ファイル名

これでひとまず回避できそう。



SurfaceViewってはやいのか???

SurfaceViewは高速に描画できる(Open GL ESよりは劣るけど),
と今日はフレーム制御処理を実装して計測してみた。

30FPSで同期とるようにしたけど,計測値がまちまち。
24FPS前後のときもあったり,
ボタンを押しまくるとなぜか33FPSあたりになったり。
CPUがさぼっているのか...。

遅い理由は計測期間と5秒に設定していたため,
平均時間を出すのに遅くなってしまっていたということが判明> <

計測期間を短くしたら50FPS前後もでるように。

ただフレーム数が安定しない。
Thread.sleep()の限界か!?

まだ自分のコードになんか問題があるのかなぁ...涙

移植するアプリは16FPS(なぜ中途半端な値にしたんだ自分www)
速度的な問題はクリアできた。

スピードが要求されるアプリを作るには,
Open GL ES使う方がいいのだろう。

勉強して作りたい品質のアプリを作れるようになるまで
かなりの時間がかかりそうなので,当分パスするつもり><

いずれは3DやらないにしてもOpen GL ESは理解しておかないとな...。
数学の行列なんて忘れたがなwww



キー入力制御

S!アプリのときはMIDP2.0で追加されたGameCanvasを用いてキーの入力値を取得していた。
(MIDP1.0からプログラムしている人は自前でキー入力制御を実装していたようですね)

GameCanvasのgetKeyStates()メソッドを実行すれば,そのときのキーの状態を取得することができます。
内部で何をしているかというと,キーのupイベントとdownイベントを取得して,
キーの押下状態を保持するというものです。

この状態を取得した後に「連続入力の無視」という処理を実装していました。
今回も役割分担として,キーの状態を把握するクラスと,
入力値からキーの伝搬をフィルタリングするクラスという構成でいこうと思います。

ボタンのイベント発生順に関してはコチラのサイトに書かれているものを参考にしました。

http://wiki.livedoor.jp/moonlight_aska/d/%A5%DC%A5%BF%A5%F3%A4%AC%B2%A1%A4%B5%A4%EC%A4%EB%A4%C8....

ボタンのup, downはOnTouchListenerインターフェースによって実装できる。

http://developer.android.com/intl/ja/reference/android/view/View.OnTouchListener.html

MotionEventにはACTION_DOWNとACTION_POINTER_DOWNがあるが,
前者は最初にタッチされたイベントで後者は2つめ以降に押されたときのイベントだそうです。
(2つ目以降って言ってるけど,本を読んだ限りではマルチタッチは2つまでだそうだ)

ビューを押した状態でボタンが押せないのは謎。
ここは改善項目なので後日修正する。

・EnumSetでビットシフト的なenumを実装できる
Androidではenumを使うとパフォーマンスが悪くなるみたいです。
http://labs.techfirm.co.jp/android/cho/1293

クラスオブジェクトや関数を使うなら通常のビット演算の方が楽そう。

とりあえず仮想パッドからキーの入力状態を管理・取得することができるようになりました。
取得の状態はログをみた内容なので,画面に出して確認したい。

ということで次はオフスクリーンイメージ部分とグラフィック周りでしょうか。
簡単に言ってみたけど一番重い> <



EGitでPullできない

フェッチはできてもプルできない。
そんなばかなぁ。
Gitについての知識があまりないんだなぁと痛感。

構成をいじることで対応できる。

http://makoll.hotcom-web.com/wordpress/?p=91

こちらのサイトで紹介されています。
自分は怖いので環境設定の値ではなく,リポジトリエクスプローラから対象の設定をしました。
(環境設定の[リポジトリーの設定]を選択したときと同じ)

これでPullできるようになりました。

構成ファイルの設定方法とかも知らないと使い切れないですね。



Android本 2冊目


Androidアプリ開発入門 (Sams Teach Yourself)Androidアプリ開発入門 (Sams Teach Yourself)
(2011/12/21)
ローレン・ダーシー、シェーン・コンダー 他

商品詳細を見る


Android本 2冊目読みました。
1冊目と比べて,
ノーマルな入門書でしたw

・Android 2.1を中心に書かれている
・お決まりの開発環境の構築, Activityのライフサイクルについて
・リソースの扱いからレイアウト,コントロールの使い方について
 (タブコントロール, ダイアログの扱い)
・HTTPのGET,POST処理
・XMLファイルの読み込み処理
・ローカライズや開発運用に関する概要

写真の観光スポットに行ったことあるか?
を問い合わせるゲームアプリを中心に話を進めています。

コントロールの扱いは丁寧に書かれているし,
特殊なタブコントロールの実装方法や,
ダイアログの表示方法についてなど
一般的なアプリをつくる上で必要な情報が書かれていると思います。

読みにくい箇所も特にないので,
入門書としては最適と感じました。

ただ第一版の出版日が2011年12月25日であるにも関わらず,
収録されている内容は少し古いので,新しい版を出して欲しい。

同じ著者で開発者向けの入門書があるようです。

Androidワイヤレスアプリケーション開発〈第1巻〉Android基本編

本屋でざっとみた内容だと,なんかしらのシステムで開発経験のある人はこちらがいいのではないかと思いました。
タイトルから無線の話かと思ってましたがw
今回読んだ本が良かったので,こちらの本も読んでみたいですね。



Eclipseでbitbucketへ既存のプロジェクトをpushする

eclipseで初めてegitを使ったのですが,全然pushできなくて困りました。

1.ローカルでgitリポジトリを作成する
2.bitbucket上でリポジトリを作成する
3.ローカルにコミットした内容をpushする

3のところで1時間程度はまりました。

1.のローカルにgitリポジトリを作成するについては,
プロジェクトを選択して右クリックでメニューから[チーム] - [プロジェクトの共有]でgitを選択していけばできます。

2.についてはbitbucket上のサイトから[Repogitoies] - [create repogitory]を選択すれば
あっというまにできます。

あとはSSHをするためにRSA Keyを作成して登録しておく必要があります。
WindowsとMac(Linux)では作成方法が違うので,この手順は省略。

問題は3のリモートリポジトリへローカルの内容をpushするところ。
ここにはまりました。

eclipse上でプロジェクトを右クリックして[チーム] - [リモート] - [プッシュ]を実行してもうまくいかない。
メニューを選択したときに表示されるダイアログに情報を入力しても,うまくいかない。

いろいろと試行錯誤していたら「Git リポジトリー・エクスプローラー」というパスーペクティブを発見。
この画面構成から作成したローカルリポジトリを選択して,展開されたアイテムより「リモート」を右クリックする。
メニューから「リモートの作成」を選択すると,パッケージ・エクスプローラーのメニュー[チーム] - [リモート] - [プッシュ]から選択したときと同じような画面がでてくる。

最初の画面にでてくる新規リモートダイアログについては

リモート名:origin
プッシュ構成を選択

でOK。

プッシュ構成の設定画面でURIを入力する欄があるので,その横に表示されている[変更]ボタンを押すと例の画面がでてくる。

URI:bitbucketのoverviewに表示されている「git@bitbucket.org:???/???.git」をコピーして貼付け。
ホスト, リポジトリパスは自動で入力されるのでそのまま。

プロとコロルは「SSH」を選択してポートは未入力。(デフォルトのポートが使用される)

ユーザ名は既に「git」と入力されているのでそのまま。
パスワードはbitbucketに登録しているアカウントのものを入力。

セキュアストアに保管はeclipse上にパスワードを保存するかどうかの設定なので,このみにあわせて。


完了すると先ほどまで止まっていたpush処理がとどこおりなく進じゃないか!!
う~ん,なんでパッケージ・エクスプローラー上からは実行できないのだろうか。
やっていることは同じなのにな。

本作業ではないところに時間がかかってしまった。
ちかれた。



仮想パッドのレイアウトを引き続き

eclipseでデフォルトのプロジェクトをつくったときに,
TextViewに「tools:context=".MainActivity"」という属性が設定されている。
これなんだろう?

同じことを疑問に思った人がいたみたいだけど英語で何いってるかわからない涙

http://stackoverflow.com/questions/11078487/android-whats-toolscontext-in-layout-files

わかる人いたら教えてほしいな。

SurfaceViewのコールバックインタフェースに本などでは紹介されていない
SurfaceHolder.Callback2というものがあった。

http://developer.android.com/intl/ja/reference/android/view/SurfaceHolder.Callback2.html

リファレンスをみるとCallbackを継承してメソッドを1つ追加しているだけなんだけど。
そのメソッドについては下記のサイトで教えてくれている。

http://d.hatena.ne.jp/Superdry/20101223/1293125035

ふむ...まだなんのことかわからんな。


interfaceのオーバライド時は@Overrideを書くとエラーになる。

http://d.hatena.ne.jp/re_shikajiro/20090502/1241276863

細かいことけど知らないことが多い。



仮想パッドのためのあれこれ

テーマの設定ファイルは以下のファイル?
android-sdk-macosx/platforms/android-10/data/res/values/themes.xml

Activityのタイトルを非表示にするには,
「Theme.Black.NoTitleBar」を設定する。

設定例については
http://www.adakoda.com/android/000156.html
を参考にするとよい。

RelativeLayoutの位置属性についてはRelativeLayout.LayoutParamsで定義されている。
http://developer.android.com/intl/ja/reference/android/widget/RelativeLayout.LayoutParams.html

RelativeLayoutに所属しているViewはこの属性によって位置を設定することができる。
日本語に訳されているサイトがあった。

http://wikiwiki.jp/android/?UI%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%2FRelativeLayout.LayoutParams

と今日は仮想ゲームパッドのレイアウトを考えて終わり。



移植する?

開発環境はなんとか整いました。
Android SDKは一晩ほっといたらDLできてました。

いざ移植開始!!
の前に他の作家さんの動向を調査してみました。
アプリゲットのマーケットを賑わせていた作家さん達は
Google Playマーケット上にも存在していて,
携帯向けに作っていたアプリを移植していました。

ただ携帯時代とは違ってあまり活況のない状態がほとんど。
やはりきれいな液晶にしてタッチパネルがあったら,
それに「特化した新しいアプリをやりたいと思うもの」なのかなと。

なのでiko2も移植するか...
Androidスマホで遊びたいと思うのか?

リメイクはする気ないので,オリジナルを維持して移植するつもりです。
最初のアプリだから見向きされなくても,作ってみるか...な?



アクセス
あなたは
キーワード
カテゴリー
最近の記事
リンク
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

WEB検索
Google

RSSフィード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。