真 もわ爛漫

しゃーら、しゃーらしゃーら

今更ballerについて書いてみる

http://mowa-net.jp/~amedama/baller/

まぁいいからやってみ。

私がプログラムを書きたいと思ったのはひとえにゲームを作りたかったからで、2001年に大学入学して以来上記2006年に到るまで割と頻繁に年二回ある学園祭にゲームだしてて、ある意味では集大成かなー、と。

毎度、何かよく分からない理由で「2週間で作る!」というのを適当なお題にしていて、サークルの慣習上よくあった「当日までに間に合わずプログラマー展示」にならないために色々自分マネージメントみたいのをやってた記憶がある。幸い、ゲーム自体が動かずに展示出来ずと言うのは一回もなかった。内輪受けのために2〜3日間の祭のためだけに隠しステージ作ったりしたことは何度もあるけど。

本当は東方やってた関係で2Dシューティング作りたかった。んだが、凝ったシューティングの肝はプログラムじゃなくて絵と音とバランスで、それはプログラマーが単体で二週間でやるもんじゃないし出来るもんでもない。当時は今のようにPublic Commonsとかの音源や絵がサクサク入ってバンドルして公開出来るという話はなかったので、必須BGMとかそういうプログラミングと割と離れたところで苦労した。

上のballerに関して言うとサークルの後輩が曲作れるということで3曲あたりhttp://mowa-net.jp/~amedama/blocker/のために作ってもらって、それを流用してる。展示の時は(割とまずいんだけど)ほんとのゲームの音源使ってた。あ、あと、とよしまハウスの人から許可もらって同人CDからいくつか借りた。恩返しは出来るといいね。いつか

というかステージの構成はむしろ展示時のBGMにテンションを合わせているのだった。

(以下しばらくよくあるゲーム開発者の自慢的裏話)

弾幕」はMAX300、「すきま妖怪」は東方妖怪小町 (永夜抄のクソムカつくラストワードの曲)、「とりあえず最後の問題」はPARANOIA -respect-とか、まぁつまり版権やばいのでネットに公開するときは全部使えるBGMにしたってところで、こういうところがプログラミング系のサークルの痛いところなんだな。もし試したければ音源差し替えれば出来る。

弾幕」はDDR MAXのExtra Stageばりの即死を明確に意識していて、曲の冒頭数秒だけ聞いてガシャーンという、当時のDDRerしか分からない悲しみを思いだせるためのステージだった。

「すきま妖怪」はラストワードの「うぐー!また死んだ!」という辛さみたいのを味わうのに調度良いってことで東方妖怪小町。リトライを100回とか繰り返してないとどういう意味かは分からないと思う。

とかね

(裏話おわり)

ゲームの実装に関して言えば、プログラマWindowsで2Dゲー作る上で調べとかなきゃいけない基礎的な点は押さえてるはず。

まず描画。言うまでもない。入力。言うまでもない。

音楽再生。これはかなり書くことがある。

まず、地味だけどwavではなくoggを再生させるのはそんなに簡単じゃない。単にライブラリをリンクするだけなんだけど。

mp3じゃないのは、mp3だと「ある開始地点と終了地点の間をループ」をするためにメモリに一度展開しないとダメで(というのは再生位置がmp3の圧縮情報上にないから)、ステージ決定からゲーム開始までのラグを可能な限り減らしてプレイヤーの気分を害さないようにするっていうそういうところに注力しようとしたときにメモリ展開とゲーム開始を同時にマルチスレッドでやって遅延を落とさずに書くのが、まぁ大層無理筋だと判断したため。

ん、分かりにくいか。ええと簡単に言うと、普通のゲームだと大抵、ステージセレクトしてからゲームが実際始まるまでに「少女祈祷中」とか、とにかくHDDにあるデータをメモリに移すために少しお待ちください的な画面が出る。んで、私はあれが大っきらいだったので、それを避けるためにかなり奮闘した、ということ。フンダンにメモリもCPUパワーもあるのになんでああいう待たせ方するかな、という不快感をずーっと持ってたので、せめてプログラマとしてはそういうのはなるたけ回避したいなー、と考えたわけ。

#そもそもなんでBGM冒頭からじゃないのかというと、BGM冒頭には大抵ループに含まれてはいけない部分がよくあるからで、何故かDirectSoundとかそういうのってそういうことには配慮してなくて「冒頭から最後までをループ」というオプションがあるのみ(だった気がする。今はどうかしらんし、もしかすると当時からあったかもしれない)。

そういう現象(話は戻り、シークタイム分ユーザを待たせるという現象)を許容せざるを得ないのはCDとかDVDとか、おっそいシークが必要なメディアを使ってるときであって、今の汎用PCでオンメモリに必要なデータを載せるのに13ms必要ない状況であれをやるのは、単純にプログラマとしてダサイ。

ちなみにPS2とかのゲーム開発だってシークを思うがままに認めてるということはないらしい。減らせるだけ減らそうと書き込みレイヤかそれより前のレイヤでデータの位置を最適化してる。グラディウス5のテストプレイについての解説で「テスト用のロムだったでシークが異様に遅くて」という下りがあったのを記憶している。んーと、特典DVDのムービーかな。

ここらへんで一つプログラマーとして意識したいのは、そーいうところで手を抜く奴とすんげー真面目に遅延をハンドルするやつで大分プログラマーの質が違うんじゃねってこと。それってユーザから見るとたまに「どうでもいいんじゃね」と思うことであったり(「少女祈祷中」と表示する)「だめなんじゃね」と思うこともあって(「シークに時間かかりすぎね?」とい思われてしまう)、つまりユーザ視点で見落とされる可能性もあれば、ふとした瞬間にユーザの支持を失うような怠惰を引き起こす可能性もある。ここらへんこそがある意味プログラマーの一つの本懐なんじゃねーかと思ったりする。MBA的にはリスク管理と言う。言わないけど。

あー、ちなみにCDとかDVDについて、シークタイムを落とせばいいってもんじゃないってのも言っておく。FF7はシークタイムを減らすためにヘッドをがりがり動かしすぎてPSキラーって呼ばれてたらしい[要出典]。

ただ、心意気はよくわかるんだ。SFCNINTENDO 64が好きだった当時の私視点から見ると、PSは「失敗して欲しい」ゲーム機筆頭だった。なぜかと言うと、単に「Loading」がウザすぎるから。そういうのをFF7の開発者が配慮してたんだろうなー、という理解でいる。結局バイハザ2にハマって以降少女祈祷中に到るまで、Loadingの悲しみが消えたことはない。ディスクではないDSですら読み込み時間かかるんだね。まぁあれはプリフェッチしきれるほどDS本体にメモリがマジでないくせして3Dのテクスチャばんばん送ってる、というのが私の予想なんだけど。

……、長かった。えーと話を戻すと、

mp3だとメモリに展開しないと特定位置にジャンプして再生するのを1フレーム13msで行うのはかんなり難しい、というのがまぁポイント。

oggはそういう点ではよく出来ていて、最初の2秒くらいをバッファに詰めたらあとは指定位置2点間のデータをリングバッファに送るだけ。「この位置がoggフォーマットのどこにあるかバイト単位でくれ」ってライブラリに聞くと「ここだぜ」とすぐ返ってくるのが非常に素敵。

ちなみに「リングバッファに送るだけ」と書いてるけどこれも自明なほどには簡単じゃない(少なくともC++初級者にとって)。しかも、割と多くのゲーム開発者 (including プロ) がこういうのをさぼってる。どうさぼってるかというと、「ディスク空いてんだから6分くらいループ再生するデータ詰め込んでお茶濁せばいいんじゃね?」という感じで、さぼってる。

これに関しては商用プロダクトで実例がある。PS2虫姫さまは難易度が一定以上だとラストステージでゲーセン版では起こらないほどの処理落ちが発生して、恐らくディスク上に保存してある、「ループ再生をあらかじめやっといた長めの音楽データ」の末尾まで到達してしまい、大変残念なBGM再生パターンを聞くはめになる。

曲とステージのシンクロだって演出なんだよぅ!大往生のラストステージで1面のメインフレーズが出るところで弾幕が薄くなってるとかそーいうのが重要なんだよぅ!斑鳩のラストステージのボスで音ズレしたら致命的なんだよぅ!

当然だけどアーケード版ではそういうアホなことは起きない。おそらく移植上の手抜き。

#あれはまぁ、会社間の不幸ないさかいで発注先を(大変素晴らしい移植であった)PS2版大往生(とガルーダ)とか作ったところから別に移して、悲しいことになったらしいという風のうわさを聞いてるのでまぁ仕方ないよね、という感じではある。
#ちなみにこの話は中の人から直接聞いた話ではないので秘密の話題でもなければ正確かどうかも不明、念のため。Tの人に会うずっとまえに聞いた話だ

ともかく、プロの人でもループ再生はたまにサボるんだな。そういうところも、上の一見するとアホみたいに適当なゲームでは割と真面目にやってる。というか真面目にやろうとはしてる。

そこに到るまでは地味にイバラの道で、別段ユーザビリティに影響を与えないのでむしろこういうところに注力してたまにリングバッファのデータをぶっこわしてゲーム全体をクラッシュさせて「お前はなにをやってるんだ?」と自問自答する日々なんてのを結構長い間やるはめになり、ゲームのプログラマーってのはつまりこう、涙目でしかない職業という印象を強く持つわけなんだ

いやそれでも、上のダサいゲームを作った私は幸い就職難逃れて就職出来たし、そこそこプログラマーとしての挟持みたいのを持てるくらいになってるし。

上のゲームからまともなシューティングの開発に移る場合に足りないのは多分スクリプト言語、具体的にはLuaかなんかのエンベッドだろうなーと。

ballerのステージは、ゲーム内に埋め込んであるエディターで快適に作れるようになっていて、スクリプト言語みたいのは要らなかった。シューティングゲームの場合はいちいち本当のプログラミング言語でなんとかかんとかするのは色々つらいし、そこらへんを非プログラマーと協力してやってくばあいにはある程度書き込めるライトな言語がほすぃ。

本当はLuaじゃなくて東方弾幕風スクリプトを拡張してステージ全部書いて、東方コミュニティの資産活用したいところではあるんだけどね。なんで「コンパイラ(というかパーザなんだけど)書きたい書きたい」と延々言い続けててでもなんでやってないかというと、東方弾幕風スクリプトが(見た感じ)魅力的で、でもそれを実装に落とし込むのが単にクソめんどくさいからというのに尽きる。今はどうか知らんけど一度ざっと見たときは、「あー、プログラマとしてはこういうのをオープンソースにして欲しいんだよなちくしょう」と割と真剣に思った気がする。ちなみに、BulletMLでは全く足りない。ぼかーABAの人を悪くいうつもりはないのです(会ったこともねーよ)。単にプログラマーが好きそうなxmlスキーマだと気が狂った演出はできねー、というところなんだと思う。そのあたり、東方弾幕風は気が狂ってるので目が赤いうさぎ弾幕とかも作れないことはない気がする。

あ……東方の過去にあったイフェクトを全部実装出来るようにと大層めんどいと思うけどね。知ってるだけでも

  • 時間を止める
  • 時間を遅くする
  • 残像を残す
  • 揺らす
  • 引力
  • ボスが3体いてルート分岐
  • ガンキャノンに見える

とかあるわけだし、他の弾幕シューまでまねようとすると

  • ボスが笑い出す
  • ボムを撃つとライフが回復する
  • 覚醒するとボスがぶち切れる
  • 回転すると白と黒のどっちかを吸収出来る
  • 特定の武器だと特定の弾だけ消せる
  • ライフが少なくなったときにでっかくなれる
  • こすると一定時間むしろ弾に当たりたくなる
  • モアイがリングレーザー撃ってくる
  • 氷みたいのが飛んできて残機全部持ってかれる
  • 昔のボスがオマージュでよく出てくる
  • 2週目最後までノーミスノーボムだとちっちゃいすごいのが出てくる
  • クソババアが異様に強い
  • ぞんびー?

とか、色々ある。……ん?

何が言いたいんだっけ、ええと。

ああ、つまりどんなにプログラマーがこだわってもデザイナー主体のゲームには絶対かなわないってことを言いたかったんです。

……あれ?

まぁスクリプトで出来ることなんてのはたかが知れててってのはそりゃそうだよね。新しいアイディアを実現出来るような包括的なスクリプトを考えれば考えるほど、単なるプログラミング言語になるわけで。Luaはよく分からんけど、多分グラ5のボスはどれにしたって書けない気がする