2012年2月28日火曜日

Androidでポリライン

シューティングゲームなんかでよく見るグネグネ曲がったホーミングレーザー

これを実際に作ろうとすると、中々に負荷がかかるです。
普通のテクスチャと違って頂点が固定化できないのでAndroidでは無理かなーと思ってたんだけどもとりあえずやってみた。

private static final int VMAX = 128;
 private static float v[] = new float[VMAX * 4];
 private static float t[] = new float[VMAX * 4];

 public static void renderPolyLine(Texture tex, Vector vlist, RenderParam param) {
  if (tex.isEnable == false) return;

  GL11 gl = Global.gl;

  int vCnt = vlist.size();
  if (vCnt <= 1) return;
  if (vCnt > VMAX) return;

  final float w = param.sx / 2;
  tex.bind();
  gl.glColor4f(param.r, param.g, param.b, param.a);
  param.setAlpha();

  float uv = 1.0f;
  Vec2 prevPos, pos, nextPos;
  float vx, vy, len;

  for (int i = 0; i < vCnt; i++) {
   prevPos = vlist.get(Math.max(0, i - 1));
   pos = vlist.get(i);
   nextPos = vlist.get(Math.min(vCnt - 1, i + 1));
   //一つ手前と、一つ先のベクトルから、向いている方向を得る
   vx = prevPos.x - nextPos.x;
   vy = prevPos.y - nextPos.y;
   len = (float) Math.sqrt(vx * vx + vy * vy);
   if(len == 0.0f)len = 1;
   vx *= w / len;
   vy *= w / len;

   //指定した横幅に広げる
   v[i * 4] = pos.x + vy;
   v[i * 4 + 1] = pos.y - vx;
   v[i * 4 + 2] = pos.x - vy;
   v[i * 4 + 3] = pos.y + vx;

   //テクスチャもセットする
   t[i * 4] = 0;
   t[i * 4 + 1] = uv;
   t[i * 4 + 2] = 1;
   t[i * 4 + 3] = uv;

   uv -= 1.0f / vCnt;
  }

  gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
  gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(t));
  gl.glVertexPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(v));

  gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vCnt*2);

  Vbo.repair();
 }
ソースはこんな感じ。 どこかで見かけたソースなんだけど、描画しようとしているある点の一つ前と1つ後から進行方向を求めて、直行ベクトル(と、その反対)に幅を広げてあげている頂点をセットする感じ。 3Dだと外積だけど、2Dなおでxとyを入れ替えるだけ。 で、UVをちょっとずつずらす(綺麗に0~1に収まるようにする)。 テストでホーミングレーザーをした図
予想通り激重いけど、馬鹿みたいにばらまかなければ使えるかな。 でも、ホーミングレーザーって馬鹿みたいにばら撒くから綺麗なのに。 だめじゃな。 ちなみに、レーザー画像を
にすればこんな感じでファンシー(?)になるのがステキング。

2012年1月11日水曜日

toURI()は使えないの?

一度ハマった穴にもう一度ハマると死にたくなるのでココに書いておく。

Intentで Intent.ACTION_SEND を指定して、ファイルを添付させたい場合に
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(Intent.EXTRA_STREAM,ここに添付ファイルのURIを);
startActivity(intent);

って感じなんだけども、このURIの指定をFileインスタンス.toURI() でURIにして指定すると、実行時でExceptionが。

結局、
intent.putExtra(Intent.EXTRA_STREAM,Uri.parse("file://" + Fileインスタンス.getAbsolutePath()));
 
ってやったら上手く行った。

2011年12月12日月曜日

a9padをバージョンアップさせたらoggが再生できくなった

a9padがここに書いてある通り、2.3にバージョンアップできるといういことで、ついついやってしまいました。

動作とかMarketとかは順調なんですが、
今まで動いていた自作のアプリが動かなく。

で、デバッグウインドウで見ると、MediaPlayer.createでnullぽ。

よくわからないんですが、createしようとするものがoggだとnullるっぽいです。
mp3にしてみたら再生出来たので。
でも、SoundPoolでは普通にoggも再生できるのです。

なにこれ。バグ?バグなの?
どうすればいいの??

2011年10月4日火曜日

AndroidでZipInputStream

最近、ColladaをAndroidで表示しようとか頑張ってたんですが(すでに過去形)

Metaseqoiaしかり、Colladaしかり、バイナリじゃなくて、テキストファイルなんですね。

なので、読みやすいという利点はあるんですが、逆に容量が増えがち(アニメーション入れると平気で2~3Mにはなる)
Androidには何気にファイル容量制限があって、機種によっては1Mを超えたくらいでオープンできなくなるし(経験則なので、実際のところは不明)

なので、荒業で「Zip圧縮したファイルを展開しながら読む」って事ができないかなーーと。

JavaにはもともとZipInputStreamという素敵なストリームクラスがあるので、リソース読むにもAssetsから直接読むにも、ZipInputStreamを挟むだけ。

というわけで、Meshクラスのロード部分抜粋
/**
  * Assetsフォルダ内のzipファイルからMeshを作成
  * @param zipName  zip圧縮されたファイル
  * @param loader 使用するローダー
  * @return
  * @throws IOException
  */
 public static Mesh getFromAssetsZip(String zipName,MeshLoader loader) throws IOException{
  int resID = zipName.hashCode();
  //既に読み込まれている
  if (meshMap.containsKey(resID)) {
   return meshMap.get(resID);
  }
  ZipInputStream zis = new ZipInputStream(Global.view.getContext().getAssets().open(zipName));
  zis.getNextEntry(); //これやらないと、ファイルが読み込めないよ。 1zipに複数ファイル入れないでね。
  Mesh newMesh = loader.load(zis);
  meshMap.put(resID, newMesh);
  return newMesh;
 }
 /**
  * リソースに登録されたzipからMeshを作成
  * @param resID  リソースID
  * @param loader 使用するローダー
  * @return
  * @throws IOException
  */
 public static Mesh getResZip(int resID,MeshLoader loader) throws IOException{
  //既に読み込まれている
  if (meshMap.containsKey(resID)) {
   return meshMap.get(resID);
  }
  ZipInputStream zis = new ZipInputStream(Global.view.getResources().openRawResource(resID));
  zis.getNextEntry(); //これやらないと、ファイルが読み込めないよ。 1zipに複数ファイル入れないでね。
  Mesh newMesh = loader.load(zis);
  meshMap.put(resID, newMesh);
  return newMesh;
 }

気をつけるのは getNextEntry(); をやってあげないと、zip内が1ファイルだとしても読み込み準備ができないということ。
ちなみに複数ファイルを圧縮しちゃった場合は知らんぜよ。

これによって、2MぐらいのColladaファイルも圧縮したら200kぐらいになってくれたので、今まで読めなかったファイルも読めるようになったりしました。

いや、もう、Colladaはアニメーションで挫けたので今更ではあるんですが。

2011年9月30日金曜日

Assetsフォルダにアンダーバーから始まるファイルを置いてはいけない

はまった! 超ハマったので、殴り書きだけど記述しておく。

Androidでファイルを直接読み込みたい時にAssetsに入れておいて、

getResources().getAssets().open(filename);

って感じなんだけど、なんと、このfilenameはアンダーバーから始まるファイルはFileNotFoundException が飛んでしまうのだ。 なーーーんじゃそらー!!!!!!!!

アンダーバーから始まるファイルなんて普通じゃねぇか・・。 なんだこのうんこ仕様は・・・。

2011年9月19日月曜日

AndroidGameBaseのソース

ちょいちょいと整形してここに貼り付けてーーーってやってたんですが、複数クラスが絡みあってる部分が多くて無理があるので、全部アップロードしてみました。

本当はgoogle codeとか使えば良いような気もするんだけども。 なんかよくわからなかったので
axfcさんところに。

とーいっても、まだまだ作り途中なんですけど。

しかもコレだけ渡されても使い方分からないかもですが。 まぁ、なんかしらのヒントにはなるのかなーとか。
傾きセンサーあたりがまだ微妙なので修正中です。

それでは、良いandroidライフを。

2011年9月8日木曜日

フィードバックブラー

GREEのスマホゲームで、「ぶっとびハリー」って物理演算系の・・・
なんというか、「ア○グリーバードのパクリ」みたいなゲームがあるんですが、そのゲーム内で
シーンが切り替わる時に、なんかカッコイイエフェクト(前の画面が残像で残る感じ。 きっと加算合成)
ぽいのをやっているのです。

これは、俗にいうフィードバックブラーってやつですな。
いいなぁ。 ローコストでそれなりのエフェクトに見えるなぁ。


・・・・ということで。 DirectXで言うところのRenderTargetの切り替え。 OpenGLだとFrameBufferObjectで、フィードバックブラーのテストをしてみた。


方法としては、1フレーム前の画面キャプチャをちょっと薄くして重ねて、またキャプチャしておくーーってやつです。

ついでに、回転や拡大したものを重ねてあげるようにすれば派手になりますな。 もちろん見づらくなりますが。

ソースについては、また今度ー。