Tonyu System 2: キャラクターの「動き」に注目した、ブラウザゲーム開発環境

この記事は[ゲームエンジン・ライブラリ・ツールの開発 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/gameengine) の 12 日目の記事です。

「ゲームを開発したい人が，既存の有名ゲームエンジン以外にどんな選択肢があるか？」というテーマのアドベントカレンダーがあるとのことで，拙作のゲームエンジン「Tonyu System 2」（以下Tonyu2）を紹介いたします．ちなみに，アドベントカレンダーの投稿もQiitaの投稿も初めてだったりします．よろしくお願いします．


# ブラウザで動くゲームを，ブラウザで開発

Tonyu System2がターゲットにしているゲームは，ブラウザで気軽に遊べる2Dミニゲーム的なものが主です（もちろん大作を作ろうと思えば作れます）．Flashをはじめとするプラグインは不要で，スマートフォンのブラウザなどでも遊べるゲームを短期間で作りたい方におすすめです．

短期間で作るゲームのために，わざわざ開発環境をセットアップするのも面倒ですので，ブラウザ自身で開発までできるようにしました．早速[動かして](http://tonyuedit.appspot.com/html/build/index.html)みてください．(トップページの「新規作成」からプロジェクト名を入力して開始）

なお，ブラウザで開発したプログラムは，そのブラウザのlocalStorageに保存されるので，共有が面倒だったり，容量の心配があったりします．試してみて興味を持った方は[ダウンロード版](http://hoge1e3.sakura.ne.jp/tonyu/tonyu2/)（Mac/Win対応．Zip解凍のみ．インストーラー不使用）もお使い下さい．

# 書けばすぐ動くキャラクター達

Tonyu2 はTonyuという独自言語でゲームを作成します．文法などはJavaScriptに準拠していますが，動作モデルをゲーム向きにカスタマイズしています．

キャラクタを右に動かす，という処理は，次のような繰り返しを書くことで実現されます．
（開発環境上でファイル→新規→名前をChara1で作成）

```js:Chara1
x=100;
y=100;
while(true) {
   x++;
   update();
}
```

(実行→Chara1を実行)

Tonyu2のオブジェクトには，いくつかの特別な意味をもつ変数があります．`x`や`y`はオブジェクトの位置を表していて，これを書き換えるだけでオブジェクトが動きます．（他にも[回転拡大縮小，透過度，グラフィックスなどを制御する変数](http://tonyuedit.appspot.com/doc/tonyu2/BaseActor.html)があります）短いプログラムでキャラクタの動作を表現できるのがTonyu2の特徴です

ところで，JavaScriptに慣れている方だと`while(true) {..}` というくだりを見て「うっ無限ループが...」「ブラウザ固まるんじゃ....」と思うかもしれませんが，ポイントはループ中に入っている[`update();`](http://tonyuedit.appspot.com/doc/tonyu2/update.html)というメソッドです．これが実行された時点で，描画のや入力処理を行ってくれるので，ブラウザが固まったりすることはありません．


#状態の自然な記述

さて，さきほどのChara1とは別に次のようなChara2を作ってみます．動きとしては，「100フレーム右に移動したあと，100フレーム下に移動する」というものです

```js:Chara2
x=100;
y=200;
for(i=0;i<100;i++) {//右に100フレーム移動
   x++;
   update();
}
for(i=0;i<100;i++) {//下に100フレーム移動
   y++;
   update();
}
```
このように，複数の動きをしたければ，繰り返しをつなげて書くだけで表現できるのも特徴です．多くのゲームエンジンでこのような動作を実現するには，「今右に動いているのか，下に動いているのか」をフラグで管理する必要が出てきます．[^coroutine]

# 並行処理が得意

これら（Chara1とChara2）を両方出現させるには，別途オブジェクト（Mainとします）を作成します

```js:Main
new Chara1;
new Chara2;
```

こうすると，Chara1とChara2が同時に移動の処理を行います．正確には，Chara1とChara2が交互に処理を行ない，`update();`のタイミングで相手の処理に切り替えるようになっています．

#こう見えてもオブジェクト指向言語

さきほどの`new Chara1;`というコードがあったことからわかるように，`Chara1`はファイル名であると同時に，クラス名でもあります．Tonyu2のプログラムは，見かけ上`class ... {   }`も `main () { ... }`もいらないスクリプト言語のように見えますが，ファイル全体が[クラス定義](http://tonyuedit.appspot.com/doc/tonyu2/classDef.html)になっています．

オブジェクト指向言語ですので，オブジェクトのフィールドへのアクセス，メソッド呼出なども普通にできます．例は省略しますが，継承やミックスインもサポートしています．

```js:Main
$c=new Chara1;
updateEx(30); // 30フレーム待機
print($c.x); // $cのxの値を表示
updateEx(30);
$c.die(); // $cを消す
```

上のプログラムに出てきた[`die`](http://tonyuedit.appspot.com/doc/tonyu2/die.html)は，組み込みのメソッドですが，もちろん自分でメソッドを定義して，呼び出すことも可能です

```js:Chara1
x=100;
y=100;
while(true) {
   x++;
   update();
}
function bigger() {//biggerメソッドの定義
   scaleX*=2;
}
```

```js:Main
$c=new Chara1;
updateEx(30); // 30フレーム待機
print($c.x); // $cのxの値を表示
updateEx(30);
$c.bigger(); // $cが大きくなる
```


#配列要らずの当たり判定

ゲームエンジンにもよりますが，当たり判定を行なう場合，対象となるキャラクタを全部配列に入れて，1個1個繰り返しで.... となることが多いですが，Tonyu2ではもっとさぼった書き方ができます。

```js:Player
while(true) {
   item=crashTo(Item);
   if (item) {
       item.die();
   }
   update();
}
```

[`crashTo(Class)`](http://tonyuedit.appspot.com/doc/tonyu2/crashTo.html)は、Classに属するオブジェクトのうち、どれかとぶつかっていれば、そのオブジェクトを返すメソッドです．

「同時に2体ぶつかっていたらどうなるの？」という疑問を持たれた方のために補足しておくと，`crashTo(Class)`はぶつかったもののうち「どれか1個」を返すという割といい加減なメソッドです[^crashTo]．ちゃんと全部処理したい場合，[`allCrash(Class)`](http://tonyuedit.appspot.com/doc/tonyu2/allCrash.html)というメソッドが用意されています．

```js:Player
while(true) {
   items=allCrash(Item);//ぶつかっているすべてのItemを配列で返す
   for (item in items) {//配列ごとに繰り返す（JSとは異なり，itemにはインデックスではなく要素が入る）
       item.die();
   }
   update();
}
```



# モダンな要素：マルチタッチとか物理エンジンとか

このゲームエンジン名前がTonyu2 となっていることから，Tonyu1はあったのか，という質問が来そうですが，あります．Tonyu1は，2001年にリリースされています．当時はまだスマートフォンもなかったため、PC（Windows）専用のゲームエンジンでした。Tonyu2では、スマートフォンでの動作も想定して、[マルチタッチ](http://tonyuedit.appspot.com/doc/tonyu2/$touches.html)などにも対応しています。また，[物理エンジン(Box2d)を簡単に用いることができるクラス](http://tonyuedit.appspot.com/doc/tonyu2/BodyActor.html)もあります．

# 豊富なサンプルプログラム

ゲームに必要な機能を実装するためのサンプルプログラムを「[用途別リファレンス](http://tonyuedit.appspot.com/doc/tonyu2/E794A8E98094E588A5E383AAE38395E382A1E383ACE383B3E382B9.html)」という形でドキュメントにまとめてあります．プログラミング初心者の方でも簡単なゲームであれば作れるようになっています．

# 作品投稿支援

Webブラウザで動くゲームを公開するには，Webサーバが必須となりますが，自分でWebサーバを持っていなくても公開できるように，Tonyu2ではいくつかの公開方法を用意しています．

- [プロジェクトボード](http://hoge1e3.sakura.ne.jp/tonyu/project/pages/top.cgi):
  Tonyu1の時代から続いている，Tonyuで作られたゲームを公開するサイトです．Tonyu2で作られたゲームの場合，ブラウザ内ですぐ実行させることも可能です
- [jsdo.it](http://jsdo.it/)への公開機能もあります→[jsdo.itに投稿されたTonyu2で作られたゲーム](http://jsdo.it/tag/tonyu)


# AltJSならではの拡張性

Tonyu2は，Webブラウザ上でプラグインなしで動作させるために，プログラムをJavaScriptに変換して実行するAltJSとして実装されています．基本的には，Tonyu2自身が提供するAPIを利用すればゲームは作成できますが，JSの生の機能を使って機能拡張もできます．

Tonyu2には`native`宣言があり，JSのグローバルなオブジェクトへアクセスを提供してます．例として，Tonyu2の実行中にQiitaのトップページに移動するプログラムは次のようになります．

```
native location;

text="Press Q to go to qiita";
x=100;
y=200;
while(true) {
    if (getkey("q")==1) {
       location.href="https://qiita.com";
    }
    update();
}
```

Tonyu1の頃からTonyu Systemを愛用していただいている[@makkii_bcr](https://twitter.com/makkii_bcr) さんは，この機能を利用して，[WebAudio経由での音楽演奏](http://tonyuedit.appspot.com/doc/tonyu2/T2MediaPlayer.html)や，[スコアのTweet機能](http://tonyuedit.appspot.com/doc/tonyu2/$WebPage.html)などを作成してくださいました．
このように，AltJSの特徴を活かした機能拡張が実際に行われています．


# 短期開発におすすめ

さきほども書きましたが，Tonyu2は短期間でゲームを作るのに向いています．
最近では，私自身，[あほげー](http://ahoge.info)という，1日で決められたお題でゲームを作る，Web上のゲームジャムに参加しています．Tonyu2の次のような特徴は，たった1日足らずでも，ゲームをとりあえずゲームっぽくすることの手助けになっていると思います．

- 思いついたらすぐWeb上で開発
- ゲームに最低限必要な機能（表示や当たり判定）がAPIで提供されている
- 記述量が少ない

拙作のあほげー投稿作品：
![koneko.png](https://qiita-image-store.s3.amazonaws.com/0/127248/84a0fe87-8f54-2554-901b-c844c627fe06.png)[子猫痩せすぎ太りすぎ](http://jsrun.it/hoge1e4/I03h)

![Elevator Anger](http://hoge1e3.sakura.ne.jp/tonyu/project/thumb/prj-Img969.png)[Elevator Anger](http://hoge1e3.sakura.ne.jp/tonyu/project/pages/viewProject.cgi?mainkey=721&)

先述した[@makkii_bcr](https://twitter.com/makkii_bcr)さんも，あほげー作品を投稿していただいています

![ikakagisu.png](https://qiita-image-store.s3.amazonaws.com/0/127248/33c28534-cefd-9c26-839a-aa895484a512.png)[遅刻なら待ってあげようイカカギス](http://tonyuexe.appspot.com/exe/makkii_bcr/Ikakagisu/info
)

![マイエレ](http://hoge1e3.sakura.ne.jp/tonyu/project/thumb/prj-Img970.png)[マイエレ](http://hoge1e3.sakura.ne.jp/tonyu/project/pages/viewProject.cgi?mainkey=723&)


# 気になることはすぐ試してみる

先月あたりに「[乱数のコク](http://togetter.com/li/1044668#c3224954)」なるものがTwitter上で話題になりました．`(rnd()+rnd()+rnd()+rnd()+rnd())/5`のように，一様乱数を複数足し合わせることで，中央に値が集まりやすくなり，「コクがでる」「まろやかになる」などの効果？が得られるとの評判でした．

実際のところ本当にまろやかなのか？というのが気になるところですが，これを視覚化して表示するプログラム ( [その1](https://twitter.com/damaguro/status/794009980319866880)， [その2](https://twitter.com/damaguro/status/794488796393803778) )を，Tonyu2のユーザである[@damaguro](https://twitter.com/damaguro)さんが作成してくださいました．[@damaguro](https://twitter.com/damaguro)さんは，他にもTonyu2の 物理エンジンのサンプル( [その1](https://twitter.com/damaguro/status/784389372460175361)，  [その2](https://twitter.com/damaguro/status/784625650078511104) ) をアニメーションGIFでツイートしてくださっています．

こういった，ゲームを構成するメカニズム，アルゴリズムをすぐに試せるのもTonyu2の特徴です．

# 今後の拡張

大作ゲームを作るために必要なレベルデザインの支援を行えるライブラリを整備したいと考えています。（例えば、敵やイベントの情報、出現テーブルなどを管理する簡易データベースのようなもの）

# 情報

- [公式サイト](http://tonyu.jp)
- ソースコードは[GitHub](https://github.com/hoge1e3/Tonyu2)で公開しています．

[^coroutine]: 他のゲームエンジンでも，いわゆる「コルーチン」という機能で実現できますが，Tonyu2では普通にプログラムを書いてもコルーチンとして動作します．明示的に「コルーチンを使うぞ」という意思表示が不要になっています．
[^crashTo]: 同時に2体ぶつかった場合，その時点でどちらかが消えて，次の繰り返し（フレーム）でもう片方が消える，という処理になります．これでもほとんどの場面では違和感なく使えます．