とりあえずひどく簡単なサンプルは動いたけど、D言語でclassを書いたらLLVMからJavaScriptへの変換が失敗したので、まだ実用までは壁がありそう。
EmscriptenはLLVMからJavaScriptへのコンパイラ。
LDCはD言語からLLVMへのコンパイラ。
なので、D言語をLDCでLLVMにコンパイルし、LLVMをEmscriptenでJavaScriptにコンパイルすれば、ブラウザ上でD言語が動かせる。原理的には。EmscriptenもD言語もSDLに対応しているのでSDLも動く。原理的には。
Windowsで動かす場合、例えば以下のコードを書く。
import SDL; immutable width = 640, height = 480; SDL_Surface *screen; int ticks = 0; void update() { SDL_LockSurface(screen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { *(cast(char*)screen.pixels + i*width*4 + j*4 + 0) = cast(char)(j + ticks) % 255; *(cast(char*)screen.pixels + i*width*4 + j*4 + 1) = cast(char)(i + ticks) % 255; *(cast(char*)screen.pixels + i*width*4 + j*4 + 2) = cast(char)((255-i) + ticks) % 255; } } SDL_UnlockSurface(screen); SDL_Flip(screen); ticks++; } extern(C): void mainLoop() { update(); } void emscripten_set_main_loop(void function(), int fps, int simulate_infinite_loop); int main() { SDL_Init(SDL_INIT_VIDEO); screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE); emscripten_set_main_loop(&mainLoop, 60, 1); return 0; }
emscripten_set_main_loopってのは、各フレームごとに呼ぶ出される関数を指定するためのもの。Emscripten使う場合は、SDL_Delayではなく、これを使う必要があるらしい。
あとは以下のようにコンパイルすれば、
ldc2 -O -ISDL hello.d -output-ll
LLVMにコンパイルされたhello.llができる。次はこれを、
python emcc -O2 -s ASM_JS=1 hello.ll -o hello.html
とすれば、LLVMから変換されたJavaScriptを含むHTMLファイルができる。'-s ASM_JS=1'オプションをつければ、asm.jsを使ったJavaScriptが生成されるので、せっかくだからasm.jsに対応したFirefox22で動かしたほうが楽しいかも。残念ながらこんくらいの単純なサンプルだとChrome26と比べて別段速くはないが。
とりあえずの問題は、最初にも書いたようにclass書くとEmscriptenがコケるところ。何も含まない空のclass書くだけでコケるのがなんとも困る。LDCとClangでclassの扱いが違うのかね。
あと、Windows上でコンパイルのためのツールを整備するのがかなり面倒。Emscriptenについては、
にある長い手順をこなさないといかんし、LDCは、
というさらに面倒な手順が必要。しかもうちの環境だと5.の最後のninja叩く前に、build.ninjaの'-D NDEBUG'をすべて消さないと、7.のLDCのビルドがコケた。
D言語でブラウザゲームが書けるようになるとかなり便利なので、このまま順当に進化してもらって実用になって欲しいところ。とりあえずclass問題がなんとかなるといいな。あと音周りもだぶんまだだよね?SDL_Mixer対応とか。
Emscripten自体はSDL_Mixer対応しているらしい。
上のページ行って、「START」ボタン押せば遊べます。左に書いてあるのがSTGL。
大昔に弾幕を書くための言語としてBulletMLってのを作ったけど、これは弾幕専用なので、敵の飛行曲線とかは書けなかった。あとXMLなので記述が冗長。この辺がかねてから不満だった。
飛行曲線、もっといえばステージパターンも含めて、STGの基本動作を安直に書ける方法があればいいのになー、ってのは前から思ってたんだけど、なかなかうまい方法が見つからなかった。いろいろ考えた結果、とりあえず今回のSTGLっていうのに落ち着いた。これがベストではないだろうが、それなりに簡易な言語仕様でまあまあいろいろ書けるというバランスにしたつもり。
STGLの特徴としては、
なので関数呼び出し=アクターの生成。
動作の記述方法はどれでも同じ。@xとかいうアクター変数をいじるとアクターの状態が変わる。
「@x <= cos(@y * 0.001) * 0.4 + 0.5」と1回言っておけば、あとは@y座標の変化に応じて自動的に@x座標はcosで波打ってくれる。
0.1__0.9で0.1〜0.9の間の小数が、2..5で2〜5の間の整数が作れます。
ザコの早回しとか、ボスを早めに倒した後の追加ザコの補充とかは無理やり書けます。
といったところ。BulletMLと比べると変数とか演算子とかいろいろ書けるようになってしまっているので、DSLとしての面白味は若干低め。論理演算はほんとは入れたくなかったんだけど、これ無いと自機の反対側から敵が出現するとか書けなかったので、しょうがなく入れた。
BulletMLの時はプロギアっぽい弾幕がそこそこ実現できるってのが目標だったけど、STGLはスターフォースやゼビウスっぽいザコがそこそこ実現できるのを目指してます。今の言語仕様でたぶん大体書けると思うんだけど、どうかなあ。ゾシーとかは厳しいかなあ。
今年自分で作ったゲームと遊んで面白かったゲームを書いてみた。
ミニゲームばかり30個少し。ほとんどFlashでプチコン少し。wonderflにはお世話になりまくりです。Haxeにも対応いただけませんかね。
一応自分で気に入っている順に書いた。上の方がお気に入り。
2011年もたぶん同じくらい作っているので、だいたいこんくらいが妥当なペースなのかなあ。ミニゲームばかりなのは、新しいルールをいろいろ考えるという、ゲーム作りのプロトタイピング部分が個人的に好きで、そこばかりかじっているからなんだけど。小物ばかり作ってると、ちゃんとした体裁のゲームを作れなくなっていくので、あまり良くない気もする。まあフリーゲーム作りは自分が好きなもの作ってればいいか。
ぶっちきりでこれだぜ!ってのがあるわけでもないので適当に並べてみた。
こちらも大作よりはちょっと遊べる系の方が増えてるなあ。Forza Horizonのゲーム達成率もぜんぜん伸びてないんですけど。ゲーム体力の枯渇を感じる。
Flashで2Dイメージを高速に大量に書きたいときは、GPUを使った2D描画を実現してくれるStarlingフレームワークを使えばいい。Flashの従来の2D描画と似たようなAPIで、Stage3Dを使ったGPUでの描画をしてくれる。
でも、Flashは従来からBitmapDataを使えばそこそこ速く2Dイメージを描画できる。わざわざStarlingフレームワークを導入する価値はあるのだろうか、と思って簡単なベンチマークアプリを作ってみた。Haxeで書いたけど、描画性能はAS3で書いた場合とそんなに変わらない、と思う。
大量の文字を上から降らせて、いろんな描画方式でFPSが確認できるようにした。マウスをクリックするたびに、以下の描画方式を切り替える。
StarlingでのBitmapDataに相当するものがTextureだ。ここではその動的書き換え可能版のRenderTextureにImageをdrawすることで文字を描画した。
注意すべきは、単に毎回drawするとひどいパフォーマンスになるので、複数のdrawをまとめてGPUに送るdrawBundledメソッドを利用すること。詳しいことは以下の記事にまとまっている。
この方式の特徴は以下となる。
Starlingで最速の2D描画方式がQuadBatchだ。QuadBatchインスタンスにimageを追加していって一気にGPUに送り描画する。
ただQuadBatchには制約があり、同一のテクスチャしか描画できない。なので普通に使うと同一の2Dイメージを大量に表示する用途にしか使えない。
その制約を何とかするためにはTextureAtlasを使う。複数のイメージを一つのテクスチャに描画し、各イメージのリージョンを切り出して描画する。こうすることで、QuadBatchを使って異なるイメージを描画することができる。TextureAtlasの詳細は以下にある。
この方式の特徴は以下となる。
Starlingを使わない場合の比較用。
BitmapDataの最速描画と言えばcopyPixels。
copyPixelsのmergeAlpha引数をtrueにすれば半透明は実現可能だった。
とりあえず手元の環境で調べた感じでは、回転、拡縮をしなくていいなら、爆速のBitmapData.copyPixelsを使っておけば、わざわざStarlingにお出ましいただくまでもない。
ただ、拡縮とかは、やっぱり使えたほうが色々と表現の幅も広がる。なのでそういった機能が使いたい時はStarlingのQuadBatch+TextureAtlasが便利だ。
まあこのへんの特性は、環境依存なところもありそうなので、一般的にどこまで言えるかは微妙かも。非力なCPUに比べてGPUがそこそこ強力な、昨今のモバイルデバイスだと、また事情が異なる可能性はあるね。