UnixのslコマンドをAndroidで完全再現!〜SL on Android〜
Androidアプリ第二号 あのUnixのslコマンドがAndroidに!?
この怪しいフォルダ型のアイコンを間違って押してしまうと・・・
アスキーアートの素敵な蒸気機関車(SteamLocomotive)がひたすら飛び回ります。
表示中も他のアプリを普通に使えて
30秒弱で律儀にexitと表示してから消えます。
こういったアプリの作り方
バックグラウンドで動作する機能をServiceというようで、
ActivityではServiceを起動してすぐ終了
public class MyActivity extends Activity{ public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); startService(new Intent(getBaseContext(),MyService.class)); finish(); } }
Serviceでは表示したいViewを作ってWindowManagerに追加
public class MyService extends Service{ public void onCreate(){ WindowManager.LayoutParams params=[TYPE_SYSTEM_OVERLAYとかでレイアウト決める]; WindowManager wm=(WindowManager)getSystemService(WINDOW_SERVICE); wm.addView(myViewToShow,params); } }
こんなことをすれば出来るらしい。
ダウンロードはこちらから!
MyDice 超シンプルなサイコロアプリforAndroid
Androidアプリ第一号作りました。
MyDice〜俺のサイコロAndroidのサイコロアプリです。
シンプルな操作 シンプルな外観 振るか画面タッチするだけ!
ぜひ使ってみてください。
https://play.google.com/store/apps/details?id=tompng.mydice
MyDiceの特徴
- 見やすい
- サイコロが大きくて見やすい。
- これより大きいと転がる余地が無くなるというギリギリのサイズ
- 簡単
- スマホを振る、もしくは画面をタップするだけ。
- とりあえず触ってみれば動いてしまう。
- 他の操作(サイコロを増やすとか)は無い。
- リアル
- 物理演算でリアルな音と動き
- 振る、傾ける、ひっくり返すとかしてみるといいかも
サイコロはこんなに便利!
- 道に迷った時にサイコロ任せに進むと、いつか必ず目的地に辿り着けます!
- 重大な決断をサイコロ任せにしても、失敗した時に神のせいにできます!
Downloadはこちらから!
Google Playhttps://play.google.com/store/apps/details?id=tompng.mydice
PCで体験したい方はこちらでどうぞ(要WebGL)
http://www.geocities.jp/flyinpng/dice20120816/dice.html
MacOSXで動くCUIな動画プレイヤー 『aaplayer』
今回は作ったツールの紹介
aaplayer ~ [CUI] AsciiArt Video Player for MacOSX ~
https://github.com/tompng/aaplayer/
ターミナルで動くシンプルな動画プレイヤーです。
sshでアニメを見たり(音は本体で鳴ります)、
作業してると見せかけてアニメ見たり、
ctrl+zで瞬時に隠したり・・・
使い方
./aaplayer 動画ファイル操作
space 再生/停止← 10秒前へ
→ 10秒後へ
ctrl+z 中断
ctrl+c 終了
q[enter] 終了
f[enter] 反転
時間[enter] 指定時間へ飛ぶ
+時間[enter] 指定時間進む
-時間[enter] 指定時間戻る
v音量[enter] 音量変更(0〜100)
ときどき次のエラーが出て再生出来ない動画があります。特に最近のmp4等。
-2010: The movie contains some invalid data.
QuickTimePlayerでは問題なく再生できるのにQTKitを使っているこれで再生できないのが謎。
WebGLで大量のパーティクルを
WebGLでパーティクルを大量に使いたい時
javascriptで全部の点の座標を指定していたら重くて数を増やせないはず。そんなときに使える技。
頂点が沢山あるVBOを作って、点の位置を全部シェーダで決定させればいい
OpenGLのPointSpriteを使えたら良いけど見つからなかったから正三角形のビルボード(常に視点を向くように調整した平板なポリゴン)を使う事にする。
サンプル
WebGLの使えるブラウザでどうぞhttp://www.geocities.jp/flyinpng/particle20120417/sample.html
on/off切り替えてから回転させて見てみると分かりやすいかも
VertexShader
uniform mat4 modelViewMatrix; uniform mat4 projectionMatrix; uniform float size,time; attribute vec2 delta; attribute vec3 random0,random1,random2,random3; varying vec2 texcoord; varying vec3 color; void main(){ texcoord=delta; //3頂点で共通の乱数を使いパーティクルの位置を決定 vec3 pos=random0*time+random1*time*time+random2*time*time*time; //正三角形になるようdeltaだけ座標をずらす gl_Position=projectionMatrix*(modelViewMatrix*vec4(pos,1)+vec4(delta,0,0)*size); color=(vec3(1,1,1)+random3)/2.; }
FragmentShader
#ifdef GL_ES precision mediump float; #endif varying vec2 texcoord; varying vec3 color; void main(void){ float r2=dot(texcoord,texcoord); if(r2>1.)discard;//正三角形の内接円外部は描画しない gl_FragColor=vec4(color*(1.-r2)*(1.-r2),1); }
VBO初期化
var numParticle=1000; var arrayBufferDelta,arrayBufferRandom=[]; function initArrayBuffers(){ var deltaArr=[],sqrt3=Math.sqrt(3); //正三角形(ビルボードの形)の頂点座標 for(var i=0;i<numParticle;i++){deltaArr.push(-1.7320508,-1);deltaArr.push(1.7320508,-1);deltaArr.push(0,2);} gl.bindBuffer(gl.ARRAY_BUFFER,arrayBufferDelta=gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(deltaArr),gl.STATIC_DRAW); for(var i=0;i<5;i++){ var rndArr=[]; for(var j=0;j<numParticle;j++){ var s=2*Math.random()-1,t=2*Math.PI*Math.random(),r=Math.sqrt(1-s*s); var x=r*Math.cos(t),y=r*Math.sin(t),z=s; //3頂点で共通の乱数値 これを使ってパーティクルの位置をVertexShaderで決定する rndArr.push(x,y,z);rndArr.push(x,y,z);rndArr.push(x,y,z); } gl.bindBuffer(gl.ARRAY_BUFFER,arrayBufferRandom[i]=gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(rndArr),gl.STATIC_DRAW); } }
描画
function render(size,time){ gl.clear(gl.COLOR_BUFFER_BIT); gl.enable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.blendFunc(gl.ONE, gl.ONE); gl.uniformMatrix4fv(gl.getUniformLocation(gl.program,"modelViewMatrix"),modelViewMatrix); gl.uniformMatrix4fv(gl.getUniformLocation(gl.program,"projectionMatrix"),projectionMatrix); gl.uniform1f(gl.getUniformLocation(gl.program,"size"),size); gl.uniform1f(gl.getUniformLocation(gl.program,"time"),time); gl.enableVertexAttribArray(0); gl.bindBuffer(gl.ARRAY_BUFFER,arrayBufferDelta); gl.vertexAttribPointer(0,2,gl.FLOAT,false,0,0); for(var i=0;i<4;i++){ gl.enableVertexAttribArray(i+1); gl.bindBuffer(gl.ARRAY_BUFFER,arrayBufferRandom[i]); gl.vertexAttribPointer(i+1,3,gl.FLOAT,false,0,0); } gl.drawArrays(gl.TRIANGLES,0,3*numParticle); }
javascript側では描画時に時間を指定しているだけで重い処理は無い。
つまりGPUが十分速ければパーティクルが100万個あっても動く!!
2段階で動きを変化させた花火っぽいサンプル
http://www.geocities.jp/flyinpng/particle20120417/fireworks.html#N=100000
うちのPCだと8万粒くらいが60fps出せる限界
線で軌跡を描画するサンプル
http://www.geocities.jp/flyinpng/particle20120417/sample2.html#N=10000
制約と誓約
棋譜ビューア更新
棋譜ビューアアップデートしました。
http://www.geocities.jp/flyinpng/kifuviewer/駒落ち将棋に対応 そして、棋譜のURLが使える様に
サンプル
http://www.geocities.jp/flyinpng/kifuviewer/#6A1yyKhr6d2prFVj6mtxVbefZXmftR9MhlQOQR0qkB/
http://www.geocities.jp/flyinpng/kifuviewer/#BPtTFnoRQCYzoVt8Jxw4Q6Vnd5Dj88sW6t1xhzx3FRkuuuS/
(2011/10/13 ちょい修正)
URLの#以下に棋譜のデータを圧縮して埋め込んでます
操作方法は前と同じで
・loadで読み込み(Lキーでショートカット)
・矢印キーorマウスホイールで棋譜再生
・flip(Fキーでショートカット)で反転
・IEでは動かない
棋譜の圧縮について
棋譜はどこまで圧縮できるのか基本的には
『移動元(9x9 or 持ち駒)、移動先(9x9)、駒の種類(成駒も合わせて14種類)、成るか否か』
の情報があれば良い。
素直に記述すると、移動元2Byte 移動先2Byte 種類1Byte+成/不成1Byteで1手あたり6Byte
ぎりぎりまで詰め込もうとしたら、1手当たりlog((81+1)x81x14x2)/log(256)=2.2Byteになる。
もっと圧縮したければ、その局面で実際に可能な手の数を実際に数えてやるといい。
例:初手は動かせる駒が20通り、金を選んだなら動かせる場所は3通り
合わせて1手が0.74Byteで収まる。
実際の棋譜で試したところ、平均で約100Byte(1手あたり0.9Byte)にまで潰せることが分かった。
・・・というのを使ってます。(A-Za-z0-9しか使ってないのと対局者名も入れてるから実際には1.5倍くらいに)
棋譜ビューア
すごく久しぶりの日記。
ちょっと頓挫してしまったプロジェクトのコードがもったいないからと残骸を組み立てて将棋の棋譜ビューアを作ってみました。
http://www.geocities.jp/flyinpng/kifuview/1_0_0/kifuview.html
使い方は、左上のloadを押して棋譜貼付けるだけ。
あとは右の棋譜クリックor矢印キーorマウスホイールで操作
先手:kilohand 後手:fivehands ▲2六歩△4二玉▲2五歩△3二玉▲2四歩s△4二飛▲2三歩成 まで7手で先手の勝ち
と、これだけじゃつまらないからと、ちょっと妙な仕掛けを試してみた。
ローカルにDLしても常に最新版が使える、自動更新機能付のHTMLファイル
http://www.geocities.jp/flyinpng/kifuview/kifuview.html ダウンロードしてからブラウザで開く
(2011/9/20 ↑間違って上書きしてしまったorz元データ無くしたし・・・ 最新版はこちら http://www.geocities.jp/flyinpng/kifuviewer/ )
初回起動時にHTMLアプリで必要になるhtml/画像/スクリプトをサーバーから取ってきて全部localStorageに保存。
次回以降は更新確認後、localStorageからindex.htmlとmain.jsを取り出して動く、という仕組み。
サーバーからデータを取得するのには、iframe(iframe内でXMLHTTPRequest)とpostMessage(異なるドメインのwindow同士での通信)を使った。
localStorageが汚れてしまう点が欠点。
この仕掛けが今後何かの役に立ってくれたらいいな
ソフトウェアのお気軽版をhtmlで配った上で、ソフトウェアアップデートも自動でできるとか。
ほむほむ。