Hatena::ブログ(Diary)

ABAの日誌

Back to ABA Games
Twitter (abagames)
カレンダー
 

2013-03-31

EmscriptenLDCを使えばD言語SDLゲームがブラウザで動かせる、かも

f:id:ABA:20130331100057p:image

とりあえずひどく簡単なサンプルは動いたけど、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対応しているらしい。

トラックバック - http://d.hatena.ne.jp/ABA/20130331

2013-03-13

STGの敵の出現パターンとか、敵の飛行曲線とか、弾幕とかを安直に書くための言語STGL作った

上のページ行って、「START」ボタン押せば遊べます。左に書いてあるのがSTGL。

大昔に弾幕を書くための言語としてBulletMLってのを作ったけど、これは弾幕専用なので、敵の飛行曲線とかは書けなかった。あとXMLなので記述が冗長。この辺がかねてから不満だった。

飛行曲線、もっといえばステージパターンも含めて、STGの基本動作を安直に書ける方法があればいいのになー、ってのは前から思ってたんだけど、なかなかうまい方法が見つからなかった。いろいろ考えた結果、とりあえず今回のSTGLっていうのに落ち着いた。これがベストではないだろうが、それなりに簡易な言語仕様でまあまあいろいろ書けるというバランスにしたつもり。

STGLの特徴としては、

  • 1関数 = 1アクター

なので関数呼び出し=アクターの生成。

  • アクターってのは敵の出現場所、敵、砲台、弾のどれか

動作の記述方法はどれでも同じ。@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はスターフォースゼビウスっぽいザコがそこそこ実現できるのを目指してます。今の言語仕様でたぶん大体書けると思うんだけど、どうかなあ。ゾシーとかは厳しいかなあ。

トラックバック - http://d.hatena.ne.jp/ABA/20130313

2012-12-27

2012年作ったゲーム遊んだゲーム

今年自分で作ったゲームと遊んで面白かったゲームを書いてみた。

作ったゲーム

ミニゲームばかり30個少し。ほとんどFlashでプチコン少し。wonderflにはお世話になりまくりです。Haxeにも対応いただけませんかね。

一応自分で気に入っている順に書いた。上の方がお気に入り。

ブラウザゲーム
プチコン

2011年もたぶん同じくらい作っているので、だいたいこんくらいが妥当なペースなのかなあ。ミニゲームばかりなのは、新しいルールをいろいろ考えるという、ゲーム作りのプロトタイピング部分が個人的に好きで、そこばかりかじっているからなんだけど。小物ばかり作ってると、ちゃんとした体裁のゲームを作れなくなっていくので、あまり良くない気もする。まあフリーゲーム作りは自分が好きなもの作ってればいいか。

面白かったゲーム

ぶっちきりでこれだぜ!ってのがあるわけでもないので適当に並べてみた。

こちらも大作よりはちょっと遊べる系の方が増えてるなあ。Forza Horizonのゲーム達成率もぜんぜん伸びてないんですけど。ゲーム体力の枯渇を感じる。

トラックバック - http://d.hatena.ne.jp/ABA/20121227

2012-11-05

Flashでの2Dイメージ描画はStarlingフレームワークで高速化できるけど注意点もある

Flashで2Dイメージを高速に大量に書きたいときは、GPUを使った2D描画を実現してくれるStarlingフレームワークを使えばいい。Flashの従来の2D描画と似たようなAPIで、Stage3Dを使ったGPUでの描画をしてくれる。

でも、Flashは従来からBitmapDataを使えばそこそこ速く2Dイメージを描画できる。わざわざStarlingフレームワークを導入する価値はあるのだろうか、と思って簡単なベンチマークアプリを作ってみた。Haxeで書いたけど、描画性能はAS3で書いた場合とそんなに変わらない、と思う。

大量の文字を上から降らせて、いろんな描画方式でFPSが確認できるようにした。マウスをクリックするたびに、以下の描画方式を切り替える。

RenderTexture.drawBundled()を使う方式

StarlingでのBitmapDataに相当するものがTextureだ。ここではその動的書き換え可能版のRenderTextureにImageをdrawすることで文字を描画した。

注意すべきは、単に毎回drawするとひどいパフォーマンスになるので、複数のdrawをまとめてGPUに送るdrawBundledメソッドを利用すること。詳しいことは以下の記事にまとまっている。

この方式の特徴は以下となる。

  • drawBundledを使っても結構低速
  • 半透明、回転、拡大縮小、色付け可能

QuadBatchを使う方法

Starlingで最速の2D描画方式がQuadBatchだ。QuadBatchインスタンスにimageを追加していって一気にGPUに送り描画する。

ただQuadBatchには制約があり、同一のテクスチャしか描画できない。なので普通に使うと同一の2Dイメージを大量に表示する用途にしか使えない。

その制約を何とかするためにはTextureAtlasを使う。複数のイメージを一つのテクスチャに描画し、各イメージのリージョンを切り出して描画する。こうすることで、QuadBatchを使って異なるイメージを描画することができる。TextureAtlasの詳細は以下にある。

この方式の特徴は以下となる。

  • かなり高速
  • 半透明、回転、拡大縮小はできるが、イメージの色を個別に動的に変化させることはできない

BitmapData.drawを使う方法

Starlingを使わない場合の比較用。

  • 低速
  • 半透明、回転、拡大縮小、色付け可能

BitmapData.copyPixelsを使う方法

BitmapDataの最速描画と言えばcopyPixels。

  • 高速
  • 半透明、回転、拡大縮小、色付け、全て無理。単にそのまま上書き描画するだけ
11/6追記

copyPixelsのmergeAlpha引数をtrueにすれば半透明は実現可能だった。

で、どれがいいかな

とりあえず手元の環境で調べた感じでは、回転、拡縮をしなくていいなら、爆速のBitmapData.copyPixelsを使っておけば、わざわざStarlingにお出ましいただくまでもない。

ただ、拡縮とかは、やっぱり使えたほうが色々と表現の幅も広がる。なのでそういった機能が使いたい時はStarlingのQuadBatch+TextureAtlasが便利だ。

まあこのへんの特性は、環境依存なところもありそうなので、一般的にどこまで言えるかは微妙かも。非力なCPUに比べてGPUがそこそこ強力な、昨今のモバイルデバイスだと、また事情が異なる可能性はあるね。

トラックバック - http://d.hatena.ne.jp/ABA/20121105

2012-10-07

HaxeでAway3Dとthree.jsをラップすればFlashとHTML5で動く3Dゲームは作れるけどね

f:id:ABA:20121007165725p:image

正直ラッパーを書くのが面倒すぎるのと、HTML5+three.js (WebGL)版があんまりパフォーマンスが出ないこと、Bloomシェーダーやらライティングやらを両方の環境で同じ感じに調整するのが難しいことを考えると、やる価値があるかどうかは微妙だ。

あとFlash+Away3D版をChrome22で動かした時に極端にパフォーマンスが悪いんだけど、これはなにか回避策があるのかしらん。

トラックバック - http://d.hatena.ne.jp/ABA/20121007
 
旧AbaPage Diary Logs
Back to ABA Games