トップ 最新 追記

hossy online - といぼっくす

ゲームの感想日記、たまにIT・プログラミングの話


04/08

_ [同人ゲーム] gdgd

[GDGD 第1回トークショー] の参加登録が始まりました。同人ゲーム製作者のトークイベント。なんというか、パネリストが激しすぎるわけで。

  • ZUN(上海アリス幻樂団 代表)
  • D.N.A.(D.N.A. Softwares 代表)
  • なりたのぶや (フランスパン ディレクター)
  • heppoko(永久る〜ぷ プログラマ)
  • 紫雨 陽樹(Platine Dispositif 代表)

参加費2500円+ワンドリンク。懇親会参加で+3000円。これで 12:00〜19:00 まで一日楽しめるなら良い感じじゃないかなぁと。定員100名とメンバーが豪華なわりには100名限定というのが厳しいかも。気になる方はお早めに。

なりたさんのお話を聞くのは、多分あゆパンの頃以来... もう9年前? いや、作る方も長いですし、ファン活動としても(-・;


04/19

_ [商用ゲーム] 「続・ゲームにおけるスクリプト言語の現状」レポートと感想 その1

4/18に、IGDA日本ゲームテクノロジー研究会(SIG-GT)第13回研究会「続・ゲームにおけるスクリプト言語の現状」に行ってきました。以下4タイトルの、50分ずつの講演会。

タイトル講演者所属資料
ごく簡単な並列処理スクリプトシステムの設計と実装小久保啓三氏HAL東京、元スクウェア24P
『サクラ大戦Ⅴ』でのスクリプト運用事例秋葉晴樹氏セガ50P
汎用スクリプト言語Xtal 設計と実装石橋立宣氏バンダイナムコゲームス39P
Squirrelスクリプトを使った実装と活用神尾隆司氏、北出智氏スクウェア・エニックス90P

順番としては、最初2つが古いシステムの設計、次が新しいシステムの設計、最後が新しいシステムの利用。

以下、その時に取ったメモを見ながら書いています。勝手に解釈している所もあり、間違ったことが混じっている可能性ありです。また、とても長いエントリになりそうなため、後半部は別にしました。

ごく簡単な並列処理スクリプトシステムの設計と実装

当時スクウェアで使われていた、ACTORモデル (wikipedia:アクターモデル) を扱う言語、ATEL (Active Time Event Language, エーテル) について。前回 IGDA SIG-GT 12「ゲームにおけるスクリプト言語の現状」に引き続き、クロノトリガーっぽいイベントをサンプルに使用。

Final Fantasy 4, 5の頃は、上から順番に処理が流れる形式だった。その頃は同時にキャラを動かそうとすると、

MES 「さあ、しゅっぱつだ
MES 「エイ、エイ、おー
MMOVE
  海賊-A  10,20
  海賊-B  15,25
  海賊-B  20,30
MEND

このように Multi Move 処理文で囲って、直列処理中でなんとか動かしていた。しかし、たとえばクロノトリガーの戦闘シーン直前、何体もの敵がマップの外側からそれぞれ個性をもって動いてくる処理を行うときに、このような記述方法では大変。そのため、アクターモデルを採用した。

[クロノ]
  bind user character
[マール]
  bind character 2
*talk turn to クロノ
        mes "急ぎましょ"
      req カエル 急がせる
      move to クロノ
[カエル]
  bind character 3
*急がせる  move to クロノ

ここで、カエルに「急がせる」というリクエストを送った後にもマールのイベントは次に進むため、マールとカエルが同時にクロノのもとに集まるイベントになる。また、マール・カエルとそれぞれの処理を独立して細かく指定できるようになり、派手な動きをしやすくなった。

Virtual Machine実装については、当時の SFC のハード的な制約がかなりあったとの事。無制限のキューやスタックは厳しいため、8段階の優先度を持つプログラムカウンタを使うようにしたり、1フレーム毎の垂直同期を見て、描画系で優先度の低い処理が溢れそうになるとそれは打ち切るような工夫を入れた。これは PlayStation になると不要になった。

スクリプターからの意見として、ACTORモデルでは今までと考え方が違って、一連のイベントを書きにくいという話が出た。この対処として「ディレクター」という仮想アクターを作って、それに制御を任せることで従来と同じような記述を続けられる。しかしAボタンを連打するようなイベントでなければ、アクターモデルの普通の書き方で十分行える。ユーザコントロールが奪われる時間を短くするよう、時間を測定して神経質に行っていた。それでも残念ながらFFのイベントシーンは長いと言われていた。

並列処理につきもののデッドロック (wikipedia:デッドロック) は、やはりここでも悩まされた。FF7 で懲りて、テレビ画面上でなにが待ち状態になっているのかが分かるようなデバッグの仕組みを入れたり、様々な工夫を行った。しかしそれでも起こってしまうものについては、「長時間のリクエスト待ちを自動解除する」という最終手段を入れることによって解決した。完全に固まってしまうとセーブすらできなく、プレイヤーから苦情が来るため。しかし、本来処理すべきものが無かったことになるというのは大きな副作用で、これは決してお勧めできる方法ではない。

QA。

シナリオの圧縮について?
容量の厳しいハードでは圧縮が大事。コードは1バイト (講演中では拡張命令は2バイトと言っていた気が)。メッセージは一般的な圧縮のみで、もともとAボタン連打にならないようテキスト量を削ったり、漢字については出現頻度や必要性からどれを使うかを選んだりした。
ウィンドウからはみ出す文字の改行は誰が指定する?
企画者が入れる。多国語対応では困ったとの事。日本語の1単語が1行になることもあったり。コンパイル時にウィンドウから溢れるときのwarningを入れていたと。
FF1〜4では行っていなかったスクリプトの採用動機は?
クロノでバトルとフィールドをシームレスにつなぐこと。

感想。多分RPGツクールを使った事のある方には馴染みがある話。古いシステムをベースとして紹介し、あとの発表に繋げるという位置づけとすると、まぁ。HAL東京の先生ということで、話し方がとても巧いと感じました。

RPGにおけるAボタンの連打をいかに減らすかというこだわりが印象的。このあとに秋葉氏の講演が続くのがまた。

クロノトリガーにはまっていた人としても楽しめました。公演中にトリガーを知っている人の挙手がありました。半分以上? さすがに多かったです。

『サクラ大戦Ⅴ』でのスクリプト運用事例

今はNintendo DSの作品を開発している秋葉氏が、2005年にリリースされたギャルゲー サクラ大戦Ⅴ の、会話パートと移動マップについて講演。

今回対象になったスクリプト+その周辺は、主にこれら。

サクラスクリプト
イベントやシナリオなど、ゲーム全般を制御するもの。C言語ライク。サクラ大戦3で原型を作成し、それから継続的に拡張・メンテナンスを行っている
マクロ形式
シナリオ担当者向けに、メッセージ部分の記述が簡単にできる、日本語で書かれた形式。NScripterっぽい。サクラスクリプトに自動変換できる
イベントリスト
移動マップの管理。データの整合性を確認しやすいよう、Excelシートで管理。入力を支援するためのVBAあり
HSL
ゲーム機向けの軽量なデータフォーマット。XML風で、テキスト形式とバイナリ形式を相互変換でき、どちらも同じAPIで扱える。HLSLとは全くの別物

サクラスクリプトのサンプル。

module SCENE0101
{
  Bg (2004)
  Face( 60 )
  
  Face( 18, 1, 1 )
  Print("……大神司令、//大河新次郎少尉を//お連れいたしました。", 15010)
  
  Nc( 17, 1, 1, 0 )
  Face( 17, 1, 1 )
  Print("大河少尉、良く来たな。//さくらくんもご苦労だった。", 15011 )
}

変数領域の新規割り当てはなく、固定長配列の32bit整数、浮動小数、文字列を扱えるのみ。

大域1: システムフラグ s000〜255
永続的に値が保存されるフラグ。ゲームクリアフラグなど
大域2: ゲームフラグ g000〜255
ゲーム開始時に初期化される
大域3: ワークフラグ w000〜127
スクリプト終了時に初期化される
ローカル1: テンポラリフラグ t000〜015
引数やローカル変数として
ローカル2: リザルトフラグ r000〜015
複数の返値

このように寿命によって変数名を変えることにより、フラグ操作ミスによる深刻なエラーを防ぐことができた。

この数値と意味のマッピングは、Excelで管理している。また、スクリプト中に生の s016 という値を書かなくても、以下のよう #define を使うことができる。

#define flag_SAKURA5_CLEARED  s16  ;ゲームクリアフラグ
#define flag_CLEAR_HEROINE    s17  ;ヒロインクリアデータ

フラグの暗号化は、詳細はセキュリティーの関係で言えないが、しっかり行っている。チートは最後までされなかった。

マルチスレッドについて。「Thread( SubThread )」のようにスレッド作成命令を使ったり、「Print("はじめまして。//<!Face(30,2)>わたし、真宮寺さくらです。<*>")」のようにメッセージに埋め込むこともできる。イベント演出で背景やキャラクタなどのアニメーションを同期させるときに、このスレッドの仕組みを使えば理論上は行えるが、製作には熟練を要し、実際サクラ3では一人しか演出をできなかった。そこで他のシステムを用意したところ、一番エフェクトに凝ることができる戦闘パートのシステムが戦闘以外でも使われるようになった。

スクリプト先読み。背景画像や立ち絵を読み込むのには時間がかかりひっかかってしまうため、Print文のようにカーソル待ち状態がある間に、先の行を実行する仕組みがある。フラグ操作や画像読み込み等の「内部状態のみ変わる」ものは自動的に数ステップ先まで進め、フェード演出やSE再生のように「画面、音声に影響する」ものについてはそこまでで先読みを自動的に止める。ちなみにこの仕組みでは、実行中のスクリプト位置が複数になり、中断セーブ時にどの状態を取るのが良いのか分からなくなるとか。そのためにサクラ対戦では、Print命令のたびにシリアライズ用のスナップショットを作るという処理を行っていた。

マクロ形式。日本語ライクなテキストをサクラテキストに変える、大きな文字列変換システム。

マクロ:
■BG 支配人室
 
サクラスクリプト:
Bg( 1001 )     ; 支配人室
fade()

基本的な置換ルール、■BG を Bg() に変換し、それが引数は最大いくつまでで、といった所まではプログラマが担当。「多少の誤字脱字も受け付けて欲しい」「未定のIDでも変換して欲しい」という無茶な要求にも対応する必要があり、このID置換定義 (支配人室→1001) はシナリオ・スクリプター管理にして柔軟に変更してもらう事で解決した。

移動マップについて。アドベンチャーシーンで同じキャラクタが同じ時間に複数の場所にいるという事を防ぎたかった。サクラⅤ以前ではイベントの自由度を重視して全てスクリプトで書いていたが、これは後から非常に確認しづらかった。書いた本人しか内容を判別できなかったり、仕様書と異なるスクリプト実装でリリースされてしまった事もあった。この乖離は、リリース後にも攻略本作成などで問題になってしまう。

これ解決するために、サクラⅤではExcelのイベントリストに一元化して、これを見ればすべて分かるようにした。条件分岐入力はExcel VBAで支援。この結果を HSL 形式で export し、ゲームに組み込んだ。スクリプトの知識が全く不要で、イベントの確認も容易。印刷すればそのまま仕様書にもなる。ただ、VBAの扱いにくさだけが難。

HSL。XMLより軽量だが、DOM風のAPIを介してアクセスするのは構造体に比べると一手間増えるなどの難点もある。扱えるデータの種類については、サクラ大戦後に改善した。

Triangles (numTriangle=2, name="Sample")
{
  Triangle (color="RED")
  {
    0.0,
    3.0,
    2.0
  },
  Triangle (color="GREEN")
  {
    2.0,
    1.0,
    4.0
  },
}

ここまでがスクリプトの話。最後に、海外版について。

メッセージが5万弱もあると、翻訳作業は数ヶ月に及ぶ。翻訳家はゲーム開発者ではなく、スクリプト内に埋め込まれている日本語をそのまま置換する、というのは難しい。そこで、海外版作成のためにExcelを使い翻訳資料作成ツールを作成した。Excelで日本語メッセージと翻訳先のメッセージを並べて書き、頻出する「………」のような言葉は他の所にもあることを示すマークを付けている。これにより、翻訳メッセージ数を圧縮している。そして、ウィンドウテキスト中におさまることを確認するために、翻訳済みメッセージの長さをpixel単位で自動計算する列も用意している。文字数でないのは、欧米向けのプロポーショナルフォントを考慮しているため。

まとめとしては、スクリプトだけで全て行わず、適材適所でツールを組み合わせていこうということ。

QA。

誤字脱字の対応方法について
手作業で対応しています
VBAは誰が担当?
新人さんをスペシャリストとして。移動マップは専属の人が
サクラ対戦はフルボイスだったと思うが、その台本は?
スクリプトから台本を作成するツールがある。ただ誤字脱字修正等で、収録がぎりぎりになったり、撮り直しになったりする事もある
海外版の仕組みは後付けという印象を受けたがどうか? また、今仕組みを作り直すならどうするか?
確かに後付け。
5MBものテキストになると、Excelで受け渡すのは限界になる。仕組みはソフトとのケースバイケースになる。
Excelを編集する担当者は何名くらいか
2名くらい。(複数人で作業の干渉はしない、という事だと思う)
スクリプターの立場は?
プランナー。プログラマはゲーム内容には関わらず、あくまでゲームを作るためのツールを提供することが仕事となっている。
プランナーもSE出身だったり同人ゲーム出身だったりで、プログラマとしてのスキルはある。

感想。ある意味ATEL以上に古さの感じられる講演でした。別の場所にあるリストで名前とのマッピングって、FORTRAN時代という印象が... 置換後のコメントが (多分) 60文字目からとか。Excel依存度が多少高いかも。仕様書と実装を乖離させないとかの工夫はいいなと思いつつ、何かプログラマが周りにあわせすぎてしまっている印象を持ちました。

HSLはいかにもYAML (wikipedia:YAML) な印象。

ちなみに前回 ブレイザードライブ の宣伝をしたものの、今回の参加者の中には残念ながら購入者がいなかったとか。販促イベントにはならないようです。

他の方のレポート

速く充実したレポートを書いている方を適当にリンク。ノートPCでレポートを書いていた方が会場にたくさんいましたし、多分もっとたくさんのサイトに書かれていると思います。
本日のツッコミ(全1件) [ツッコミを入れる]

_ TrackBack [http://d.hatena.ne.jp/darc0113/20090421/1240283652 d’Arcのは..]


04/21

_ [商用ゲーム] 「続・ゲームにおけるスクリプト言語の現状」レポートと感想 その2

前回のエントリに引き続き、IGDA日本ゲームテクノロジー研究会(SIG-GT)第13回研究会「続・ゲームにおけるスクリプト言語の現状」 のレポートです。飛ばしている所も多いです。他の方のレポートのついでくらいに見ると良いかも。

汎用スクリプト言語Xtal 設計と実装

バンダイナムコゲームスの石橋氏の発表。会社としてではなく、個人として。

Xtal は Lua の代替を狙った汎用スクリプト言語。google code で公開 している。Xtal は正しくはクリスタルと呼ぶ。2006年から eXTreme Agile Language の略となっているがこれは後付けで、2002年にはクリスタルという名前になっていた。Rubyのように宝石の名前にしたかったのと、FFの最高級宝石の意味を込めて。ライセンスは MIT。Google code に登録しやすいという理由で、できれば Public License にしたかった。

Xtalを作る上で大きな影響の1つがRuby。さくさく書けることに感動した。80:20のパレートの法則 (wikipedia:パレートの法則) にあるとおり、80%の速度への影響が少ないコードは、効率の良いスクリプト言語で書いても良いはず。しかし、開発当初の2002年には、Rubyにはゲームや組み込みに使うには「バイナリコードにコンパイルできない」「浮動小数点がオブジェクト」「ガベージコレクトのラインが長い」などいくつかの問題点があった。

次に Lua に出会った。これは軽く速く組み込みやすい。しかし、「グローバル変数の扱い」「C/C++ との親和性 (配列が1 origin、ブロック、--コメント)」に不満があった。

そこで、Xtalを開発した。ただ、不満があるから作りたいと言うよりは、自分が欲しい言語を作りたかったという理由。登山家が、山がそこにあるから登る、というのと同じ。

文法紹介。「変数」「制御構文」「クラス」これらはC++風。「ファイバー(コルーチン)」「Rubyのようなブロック」あり。詳細は公式サイトのマニュアルを参照。

変数定義と初期化は、"foo = 0;" という代入風の書き方でなく "foo: 0;" と、タイプ数を増やさずに分けて書いている。

構文解析 (wikipedia:構文解析) と字句解析 (wikipedia:字句解析) について。最初はこの2つを一緒に行っていた。拡張しやすいと思い途中から分離している。しかしまた戻すかもしれない。構文解析については Yacc を使わず手書きしている。Boost.Sprit はコンパイルが遅く使っていない。将来的には自作ライブラリに置き換えたい。

バイトコード (1バイト=256) はJavaを参照に独自で生成している。ワードコード (2バイト=65536) も試し、1〜2割の実行速度の向上を確認したが、そのために命令長が2倍になるのは痛いので、前者のままにしている。

オブジェクト管理は、Lua と同じ Variant (Any) 方式を採っている。「整数」「浮動小数点」「その他」の3種の型の種類を示す int を全ての構造体に入れている。

ガベージコレクション (GCアルゴリズム詳細解説 - livedoor Wiki) は参照カウンタ+Mark&Sweep方式を採っている。オブジェクトの開放は自動でなく、gc関数やfull_gc関数を明示的に呼ぶ。これは、消す処理が重いことや stack overflow になることがあるため。他の方式も検討したが、保守的な GC はもともとの動機が Ruby のガベージコレクションへの不満があったため没、世代別GCやインクリメントGCは、ライトバリアの仕組みをC/C++とスクリプトの世界を頻繁に行き来する時に維持するのが困難という理由で使えなかった。

環境依存部分はカスタマイズが容易になっている。

バインダはXtalでも必須。Luaではtolua, luabind、SquirrelではSqPlusが有名。この仕組みは Modern C++ Design (amazon:Modern C++ Design) にあるテンプレートを駆使している。ただしコンパイル時間の低下や、移植性低下にも繋がっている。

Xtalの欠点としては、実績がなくある意味地雷原。実行ファイルのサイズがLuaの2〜3倍と大きく、実行速度も負けている。

開発を振り返ると、理想の言語を追い求めすぎずに妥協すれば良かったと反省。理想の言語は体調によって変わる。LISPになりかけた事もあった。

今後の予定と最後に。そしてQA。

感想。とにかく笑い溢れるセッションでした。発表経験というよりは、もうこれは人柄で。なんとも羨ましい。プレゼンテーションが下手だから 未踏ソフトウェアに申し込んでいなかったとの事ですが、全然そんなことは。是非これを機会に挑戦頂きたいところです。

枯れていないライブラリを商用で使うのはかなりリスクがあり、その点で Lua が強いのですが、Xtal も流行ればいいなぁと思いました。人柱さんに期待。

Squirrelスクリプトを使った実装と活用

スクウェア・エニックスの神尾氏、北出氏の発表。WiiWare の「小さな王様と約束の国 Final Fantasy Crystal Chronicles」の製作にあたって、Squirrel (読み方は様々だが、ここではスクワール) を使用したときのノウハウの公開。このセッションのみ、言語を作る方ではなく使う方法について。

Squirrel は C/C++ ライクなオブジェクト指向の組み込み向けスクリプト言語。標準拡張子は ".nut"。6000行ほどのC++で書かれていて、ソースコードは公開されている。

暫く文法の解説。Google で検索するとわかりやすい日本語ドキュメントが見つかる。(Squirrel2.2 リファレンスマニュアル 邦訳や、Squirrel - 組み込み言語Wiki 参照)

関数
引数に型がないのでコメント推奨
戻り値は1つ
Array, Table
Array は 0 origin の配列
Table は連想配列
Class
コンストラクタはあるが、デストラクタがない
メンバ変数について、コンストラクタで初期化しないとstaticのように振る舞うことに注意 (なぜ?)
roottable()
グローバルに定義されている関数や変数のテーブルが取れる
これを使い、if ("hogehoge" in getroottable() {...} のように、関数が定義済みかどうかをまるで #ifdef のように調べられる
また、クラスの名前の取得、定義済みのクラスや関数の開放もできる

スクリプトの使い方は、AI作成やイベントスクリプトと言った限られた機能のみスクリプトを使う方法、ゲームコードもデータも全てSquirrelで記述するというどちらの方法もある。

SquirrelからC++のコードを呼び出すにはバインドが必要。このためにSqPlusを使う。関数・クラス・定数のバインドが可能。C++からバインドしたクラスを Squirrel上で派生する事も可能。

別スクリプトの import が比較的簡単に行える。ソースを分けて管理すると便利。ある import したファイルにバグがあったときに、そのファイルだけ修正して再読込すれば、実行を一旦終了せずに迅速に回復できる。

C++から読み込んだスクリプトの呼び出しもできる。スタック操作がややこしいことに注意。

組み込み時の注意は3点。

  • C++で生成したクラスのポインタをそのままSquirrelに見せる場合、try〜catchを使い、Squirrelのスタックダンプを呼び出すか、呼び出せるようにしておくのがお勧め
  • または、ポインタをそのままSquirrelに出さず、idで管理する方法もある。この場合、C++でポインタを引く前に、idが適正かどうかを確かめる
  • 関数の引数が多すぎるとエラーが出る。標準は7個。それ以上必要な時には sqplus.h の template を書き足せばよい

製作初期には、C++ と Squirrel のバインド作業が多く、けっこう大変。データを Squirrel で持たせる場合は、.xml などから .nut に変換するコンバータを作っておくと便利。

バインドを行う工夫として、ツールでバインドコードを自動生成するのを行っている。たとえば、次のような C++のコード SQVector.h に SQREG_* マクロでバインドする変数と関数を書いている。これに対し SqReg.rb スクリプトを実行すると、バインドコード SQVector.sqreg が自動生成される。Squirrel 側で使えるかどうかの情報も C++ のヘッダファイルだけ見れば分かる。(以下、ハンドアウト P52-53 のコードを部分的に省略したもの。赤字がうまく印刷されていないため、間違っている可能性あり)

class SQVector
{
public:
  static void BindSquirrel();
  
  float x, y;
  SQREG_CVAR( x, "x" );
  SQREG_CVAR( y, "y" );
  
  SQVector( float x, float y );
  void set SQVector( float x, float y );
  SQREG_CFUNC( Set, "Set" );
}

Squirrel 上のデータを foreach, typeof を使えば比較的簡単に .nut 形式に出力できる。Wii のデバッグがハードウェアの都合で高速に動かない事もあり、ファイル書きだしが役立った。

デバッグでは、ランタイムエラーが厄介。変数がない、typo、シンタックスエラー、型が違うなどなど。命名規則やエディタの補完機能である程度は解消できるが、動的なシンボル・ラベル作成には対処できない。アドレス例外などでスタックダンプが出ないときには、以下の関数を用意しておき、IDE でプログラムカウンタをここに飛ばすことをお勧めする。

void ScriptManager::PrintCallStack()
{
  sqstd_printcallstack( SquirrelVM::GetVMPtr() );
}

スクリプトエラーが発生したときには、スクリプトの呼び出しを空回りやブレークポイントにより一旦中止させ、その間にソースファイルを修正して、タイムスタンプが更新されたスクリプトを読み込み直す、という流れを行う。class インスタンスの場合は回復に手間がかかる。

VisualStudio上でのデバッガのデモ。丁度講演の日の朝に、Squirrelの掲示板から取得した。

気をつけること。

  • SquirrelとC++で頻繁な往復をしないよう、目的に特化したI/Fを用意する。たとえば GetPos() → SetPos() するより、AddPos() 1回で済ませた方が良い。
  • 細かいメモリーブロックが作られることに注意。Table は手軽だが Array 容量を消費することを意識する
  • VMのスタックサイズ調整。sqvm.cpp_stack.resize() にブレークポイントを張り、何度も通る場合は SequirrelVM::Init() でのサイズを大きくして頻繁な realloc を避けること
  • GCを実行するとフレームレートに影響する事があるので、画面切り替えやフェードのタイミングという影響の少ない場所がお勧め。デフラグを防ぐためにリソース入れ替え前が良い

FFCC 小さな王様と約束の国での活用。287ブロックの小さなWiiWare。約70%のプログラムがSquirrelで書かれている。その中にはデータやメインループも含まれる。スクリプトのオーバーヘッドは10%程度。

開発中の FFCC My Life as a Darkloadについて。海外版のリリースは決まっており、日本語版は未定。ゲームデザインを新しく起こしながらも、小さな王様のシステムをなるべくそのまま使っている。講演前日に調べたところ、C++ソースで94%、Squirrelソースで30%が流用。スクリプト部分について、スピード感のあるトライアンドエラー開発が行えた。

工夫した点として、try, catchで実行時エラーを捕らえ、ゲームを再起動することなく復帰させていた。ただし、難しい場所については再起動していた。また、実用可能な速度でデバッガ eclipse / SQDev が動かず、いわゆる printf デバッグを行っていた。

まとめると:

利点
素速いリトライが可能、短い時間で形にできる
柔軟なデータフォーマットと、スクリプトで細かな変更にも容易に対応
コールスタックが協力で、問題の把握が容易
IDEが無くても製作やデバッグ可能
難解なメモリ破壊系のバグが起こりにくい
注意点
メモリに注意。主にガベージコレクタ
ランタイムエラーによるデバッグコスト増に注意
引数や戻り値の型がないため、しっかりコメントを

今回は小さな王様とMy Life as a Darkloadでゲームコードの部分を取り替えた事例の紹介。今後は同様に、ハードとシステムの部分を取り替えるなど、色々な活用方法が考えられそう。

QA。(ここでは半分程度)

ライセンスが言語決定の理由の一つか
マニュアルに Squirrel を使用したと書く必要がないのは確かに気が楽だが、それだけが採用の理由ではない
実行中の再コンパイルで、参照を確実に切ることはできるか
完璧ではなく、問題がおこりそうな限定した箇所に対して行っていた
プランナーとプログラマの担当分担は?
イベントスクリプトがプランナー。それ以外がプログラマ
アクションゲームでも同じように使えるか?
よりリアルタイム性が要求されるため、ゲームジャンルに応じてもう少し限定して使うのでは
どこより上のハードで使えるか
今の方法ではWiiが下限。DSではスペックが不足する
360, PS3はハード的には申し分ないが、ソフトウェアの規模が大きすぎ、スピード感だけで作ると大変なことになるかもしれない
Squirrel にはバグが残っていると掲示板で見かけたが
徐々に良くなっている。標準的な使い方をしていればあまり地雷を踏まない。
もし不具合があったとしても6000行のソースコードがあり対処できる、というのが採用のきっかけの一つとなった

感想。これ、かなり高度な「今の」ノウハウの公開かと... スクウェア・エニックスの太っ腹さに素晴らしいと。Squirrel を名前を聞いたことしかない人には、最初の文法紹介の密度にどうしようかとも思いましたが、結果的には一番満足度の高いものに。

サンプルコードがあると、よりSquirrelの強力さが分かります。さすがにそれを全て載せるのは自粛。興味がある型は、こういう機会に是非参加することをお勧めします。

_ [商用ゲーム] 「続・ゲームにおけるスクリプト言語の現状」その3 yield

XtalのQ&Aで、yield に返値が取れるか、C# はダメだけれど Xtal は大丈夫、というような話がありました。これの意味が良く分からなかったもので、ついでに。

0*1 + 2*3 + 4*5 + 6*7 + 8*9 = 140 という式を、無理矢理 ruby の yield を使って書いてみました。

def sum2(ary)
  i = 0
  sum = 0
  while (i+1 < ary.size)
    sum += yield(ary[i], ary[i+1])
    i += 2
  end
  sum
end
 
ary = Array.new(10) {|i| i}
x = sum2(ary) {|i, j| i * j}
puts x

sum += yield のように値を得られます。

では C# では。C# に慣れていなくて調べながら書いたもので、間違っていたらごめんなさい。

using System;
using System.Collections;
 
namespace YieldSample
{
    class Program
    {
        public static IEnumerable Sum2(int[] ary)
        {
            int i = 0;
            while ((i + 1) < ary.Length)
            {
                int[] a = new int[]{ ary[i], ary[i+1] };
                yield return a;
                i += 2;
            }
        }
 
        static void Main(string[] args)
        {
            int[] ary = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
            int sum = 0;
            foreach (int[] a in Sum2(ary))
            {
                sum += a[0] * a[1];
            }
            Console.Write(sum);
        }
    }
}

yield は return を修飾していると思うと、確かに return が返値があるとおかしいかも。

言語を選ぶときの切り口って色々あるんだなと思ってみました。これだけの話が1分くらいのQ&Aの中につまっていても分かるように(汗)。

...と、うちはゲーム製作ではなくてゲーム紹介を中心とした日記でして(汗)、多分こういうプログラミングな話題はこれくらいにすると思います。もしこれっきりにならないとすると、続じゃない方のほったらかしにしているレポートを書くくらいで(汗汗)。