4月1日ですが、ActionScript3で、Namespaceを使ってオーバーロードをスマートに実現する方法を思いついたので書きます。
今回、ちょっとコードが長いので、FlexBuilder2 Beta2用のプロジェクトをそのまま固めてアップしました。ダウンロードはこちら。これを見ながら読み進めてください。
このプロジェクトには、org.be_interactive.overloadパッケージと、サンプル用のOverload.asが含まれます。
org.be_interactive.overloadパッケージには、
- OverloadExtensionクラス
- 4つのネームスペース
が定義されています。
とりあえず使い方ですが、まず
import org.be_interactive.overload.OverloadExtension; import org.be_interactive.overload.overload_String; import org.be_interactive.overload.overload_Int;
クラスと必要なネームスペースを読み込んで、
class Hoge
{
import flash.util.trace;
overload_String function fuga (str:String) : void
{
trace('String', str);
}
overload_Int function fuga (n:int) : void
{
trace('Int', n);
}
}
引数の型に合わせてネームスペースを変え、同じ関数名でオーバーロード用のメソッドを定義します。そして、
public function fuga (...args) : void
{
OverloadExtension.execute(this, 'fuga', args);
}
実際に呼び出されるpublicメソッドを作り、 OverloadExtension.execute(ターゲット, 呼び出すメソッド名, 引数配列) で呼び出します。これで準備完了。なんとこれだけで、オーバーロードが可能になります。
var h:Hoge = new Hoge();
h.fuga('hello, world'); // 出力:String hello, world
h.fuga(1); // 出力:int 1
但し、デフォルトでは 引数なし/String/Int/String+Int のオーバーロードしかサポートされていないので、これを拡張する方法を紹介します。
まず、オーバーロード用の適切なネームスペースを用意します。ネームスペース名は引数の型を並べるのがいいかと思いますが、実際は何でも構いません。
public namespace overload_String_String = 'http://www.be-interactive.org/OverloadExtension/String/String';
次に、OverloadExtensionクラスにネームスペースを登録します。これは初期化段階で1度呼び出せばOKです(例えばDocumentRootのコンストラクタ)。
OverloadExtension.register(overload_String_String, String, String); // 引数は、(ネームスペースへの参照, Class, Class, ...)
最後に、先ほどと同じようにメソッドを定義すれば完了です。
overload_String_String function fuga (str:String, str2:String) : void
{
trace('StringString', str, str2);
}
デフォルトでは、初期化段階(OverloadExtension#initializer)で次のように4つ登録されています。ここは自由に変更してもらって構いません。
register(overload_default); register(overload_String, String); register(overload_Int, int); register(overload_String_Int, String, int);
OverloadExtensionの実装の説明は省きます。興味がある人はコードを読んでくださいな。ちなみに、このライブラリは自由に使用/改変してもらって構いませんが、できればパッケージは変えないでください。
昨日のエントリがfladdict.netさんで紹介されて浮かれております。という訳で、続きです。
そもそも、どういう時にスクリプトエンジンが必要になるのか?という所ですが、元々このエンジンはゲームを製作しやすくしようプロジェクト(今勝手に命名)の一環として作ったもので、やはりゲーム系なんかで役に立ちそうです。
とりあえず、このスクリプトエンジンの特徴と仕様を書いてから、いくつか使用例を挙げてみるので、そこからスクリプトエンジンの使い道を探ってみてください(笑
- スクリプトエンジンの動作サンプル
- スクリプトエンジンのコード一式(リファクタリングしきれてません。すいません)
JavaScriptやActionScriptなど、ECMAScript系のスクリプトには、evalという、引数の文字列をスクリプトとして実行するメソッドがあります。・・・あるはずなんですが、ActionScriptではevalはマトモに動きません。
というわけで、この辺でも書いた、ActionScript上で動作するスクリプトエンジンを作りました。やっと完成した・・・。時間かかった・・・。
動作サンプルはこれです。基本的に文法はECMA-262 3rd Editionにのっとってます。ActionScript1的な感じ。
独自拡張として、スクリプト中に
suspend;
と書くと、一旦Flash側に制御が戻るようになっています。そして、Flash側が再びスクリプトを実行したときに、中断したポイントから再開されます。(マイクロスレッド)
上のサンプルでは、Flash側に
this.onEnterFrame = funciton () {
virtualMachine.execute();
}
と書いているので(少し略してますが)、スクリプトを
loop {
trace('Hello');
suspend;
}
と書けば(loopは無限ループ構文)、毎フレームHelloが出力されることになります。
とりあえず、体が休息を求めているので詳しいことはまた今度書きます。それまで上のサンプルを弄って待っててください(笑
出来たばっかりでごちゃごちゃしてますけどコードも置いておきますので興味ある人はどうぞ。
// コード
var code:String = [
"loop {",
" trace('Hello');",
" suspend;",
"}"
].join("\n");
// コンパイル
var parser:IParser = new Parser(new Scanner(code));
var vm:VirtualMachine = new VirtualMachine();
vm.setByteCode(parser.parse());
// trace関数のエクスポート
vm.getGlobal().trace = trace;
// 実行
this.onEnterFrame = function () {
vm.execute();
}
みたいな感じで実行できます。
テストも終わり、ActionScript三昧な日々、いかがお過ごしでしょうか。yossyです。
先日、ウチにNintendoDSが来まして(俺が使うんじゃないですけど)、ちょっと触らせて貰いました。「脳を鍛える大人のDSトレーニング」ってソフトだったんですが、うおー、これペンで書いて答えるのか!手書き文字認識か!いまどきのゲームはそれぐらい出来なきゃいかんのか!これはFlashでもやるしかねぇ!
オープンソースの手書き文字認識エンジン「巴」をベースに、少し改変して認識エンジンと辞書をFlashに移植。ショボショボ学習機能も追加してみました。速度の割に、そこそこの精度で認識してくれます。
巴がLGPLなので、一応これもLGPLということで。ソースはこちら。AS2.0用のクラス(製作中のゲーム用フレームワーク「Spark」のパッケージとして提供)と、使い方のサンプルのflaファイルです。
色々入力してみるとオモロー。辞書に図形を登録して遊ぶ事も出来たり。
なんてものを作りたいなぁ、と思った。名前の通り、Flashでゲームを製作する場合に使うと便利なライブラリ(クラス群)。
今のところ昔書いたヤツを書き直したタスクシステムしか無いんだけど、入力関係とかユーティリティ、Flash8が出たらゲームで使いそうなビットマップ処理/映像処理(Webカメラ差分判定とか)なんかを盛り込めば、それなりに需要がありそうな気がする。
とりあえず、試しにタスクシステム部分を公開してみる。ダウンロードして解凍したら、フォルダをクラスパスに通るようにすると便利。
ActionScript2.0 Game Framework (ASGF) ※開発途上版
タスクシステムに関する説明とサンプルは続きで。



