Dartの演算子オーバーロードを使ってみる

たまにはブログも更新しないと、ということで。以前Flashで作ったものをDart+HTML5 Canvasに移植したものです。ドラッグでポイントを動かせます(Operaで動かないのは……なんででしょう?)。リンク先にソースコードも置いてあります。

これはもともと、ActionScriptに演算子オーバーロードがなく、ベクトルの計算などが書きづらいのをどうしようかと試行錯誤したものだったんですが、例えばpositionとvelocityがVector2クラスのインスタンスだとして、

position = add(position, mul(velocity, deltaTime));

とでもするしかないかなという感じでした(詳しくは省きますが、実際にはこれじゃダメでしょう)。DartならVector2クラスにoperatorを定義すれば、

position += velocity * deltaTime;

のように直感的に書けます。

演算子オーバーロードというと、そんなもの要らないよと言う人も多いのですが、ベクトルや行列の計算にはあるととても便利なのです。ゲームプログラム(とりわけ3Dの)でC++が使われる理由のひとつとして、演算子オーバーロードで幾何学計算が素直に書けて、しかもコンパイラの最適化で十分に速いアセンブリコードが出力されるというのが大きいと思います。UnityのJavaScriptも、ベクトル等の計算が普通に書けるよう独自に拡張されています。

そんなわけで、Dartに演算子オーバーロードが入ってきたのは嬉しいです。……が、上の例がfrogcでJavaScriptにどう変換されるか見てみると……いちいち型チェックしてるんですか、これ。オーバーヘッドがかなり大きそうで不安w DartネイティブのVMに期待って感じでしょうか。

position = $add$(position, ($mul$(velocity, deltaTime)));

...

function $add$complex$(x, y) {
  if (typeof(x) == 'number') {
    $throw(new IllegalArgumentException(y));
  } else if (typeof(x) == 'string') {
    var str = (y == null) ? 'null' : y.toString();
    if (typeof(str) != 'string') {
      throw new Error("calling toString() on right hand operand of operator " +
      "+ did not return a String");
    }
    return x + str;
  } else if (typeof(x) == 'object') {
    return x.$add(y);
  } else {
    $throw(new NoSuchMethodException(x, "operator +", [y]));
  }
}

function $add$(x, y) {
  if (typeof(x) == 'number' && typeof(y) == 'number') return x + y;
  return $add$complex$(x, y);
}

...

ついでに、演算子オーバーロードは必要なんだ、という他の方の証言を。

JavaScriptになかなかつかない理由。いずれはなんとかなりそう?

余談ですが、DartといえばHello, WorldをJavaScriptに変換したら17000行になったというのが話題になりましたけど、今はだいぶ小さくなってます。このサンプルの出力(CanvasTest.dart.js)が150KBくらいです。Closure Compilerを通すと55KBくらいになるんですが、動かなくなるので、ちょっと調べないといけなさそうです。

(追記)ちなみにCoffeeScriptでも演算子オーバーロードの要望が何度も挙がって都度却下されているようなのですが、どうも、動的型言語からJavaScriptへのトランスレートでは非効率な変換結果にならざるを得ないようです。a + bという式があったときに、aとbの型が実行時まで決まらないので、関数の呼び出しに変換するべきかどうか分からないと……。

C#からJavaScriptに変換するJSILRaytracer Demoを見ると、演算子オーバーロードが素直に変換できているので気になります。ただ、こちらは出力が結構大きくなってしまうようですが。

2012年4月2日

格ゲーコマンド入力判定


対戦格闘ゲームの必殺技コマンド入力の実験をしてみました。カーソルキーまたはテンキーでレバー、スペースキー・Ctrlキーでパンチボタン、Shiftキーでキックボタンです。技の名前は気にしない方向でひとつ。

判定方法は、リングバッファに過去一定フレームの入力状態を蓄積して、バッファに各コマンドのパターンが含まれているかどうかを毎フレームチェックしています。

いろんな種類のコマンドを、できるだけ簡単なスクリプトひとつで検出できるよう考えてみたんですが(コナミコマンドも大丈夫!)、実際のゲームで汎用的に使えるかどうかは自信がないです。たぶん何か不都合が出てくると思う。そうでなくても、たとえば溜めコマンドなら、溜めはじめた時点でモーションを移行したりする必要が出てくるでしょうし。

Warp Smashにしょーもないバグを発見。あとでこっそり直しておこう……。

2009年5月20日

ゲームプログラマになる前に覚えておきたい技術

買いました。パワースマッシュ3などに携わったセガの現役プログラマさんによる貴重な入門書。これはまた人が殺せそうな……今までに出たゲーム制作系の書籍で一番分厚いんじゃ?

一通り目を通したけど、やっぱり自分は数学周りがボロボロだなあと。たまに透視変換行列とか頑張って導出してみたりするんだけど、導出過程にまったく自信が持てない、そんなレベル。きちんと消化させてもらおうと思います。

巻末で紹介されてる「オイラーの贈物」だけど、再版しないのかな。あちこち書店や古本屋を見かけるたびに探しまわってるんだけど全然見つからない。どうもこの本が手に入らないことが数学を再勉強しない理由になってしまってたりします。よほどいい本だとあちこちで評判なので、スルーすると土台がおかしくなりやしないかという。所詮は言い訳なんですけどね。Amazonの最安値が5,995円。いっそタイ米をはたいてしまおうか。いやタイ米ではなく。

ボンバーマンを侮っていたことに気づきました。ちょっとFlashで作ってみるつもり。

2008年11月27日

トップページ
プロフィール

はてなブックマーク
wonderfl