第79回 ゲームプログラマに必要な食材(ゲームプログラミングは難しいのか?) 99/9/28

yaneuraoGameScript2000(以下YGS2K)を公開してから、二ヶ月ほどが経過した。実際に、C言語ちょっとやったけど、わからんからやめちゃってたよーんというような人もこれを機にゲームを作ってくださったようで、高校の文化祭のためにYGS2KでRPGを作っただとか、C言語の勉強用としてYGS2Kしておられる方もおられるようで、作者冥利に尽きるというものである。

まー、プログラミングってなんどすか?って人には、ちと辛い面もあるみたいだけど、C言語をちょこっとやって、そのまま挫折した人たちには夢と希望を与えることが出来たんでないかなーと、手元に頂戴しているメールの数々から(手前味噌的に)判断させていただいている。そんなわけなもんで、この部分を引用して

> 夢と希望を与えることが出来た

 お前は、魔法使いサリーか!!

だなんて突っ込みは勘弁して欲しい。(誰もせんてば、そんな突っ込みは…)

そもそもゲームプロミングというのは、そんな難しいものではない。10数年前には、マイコンBASICマガジンにプログラム作って投稿していた小学生なんて山ほどいたし(私もその一人だった)、誰でもゲームは簡単に作れる。

それがWindowsの出現以降、プログラミングの敷居が異様に高くなった。それは、開発ツールの値段の高さ、技術資料の多さ、買わなければいけない本の数etc…による環境の変化によるものだと思う。ゲームは、もはや、遊ぶだけのもので、作るべきものではなくなったと誰しもが思った。(というか、少なくとも、やねうらおは、そう思った)

では、ゲームを作るのは、本当に難しいのか?と問われれば、それはもちろんNo!だと言いたい。Windows初心者にとっては、ビットマップやwaveファイルを読み込むだけでも一苦労だろうが、そういう非本質的な部分をすべて除けば、ゲーム自体を作ることはたいして難しいものではない。初心者の方々がYGS2Kで次々と作品を作り出していく姿勢を見ていると、そんなことを感じてやまないのである。

彼らの作品のなかには、シェアレジに登録されているシェアウェアより、よっぽどCoolなものもある。どれもこれも初心者の作品とは思えない。逆に言えば、彼らには、もとからそれだけの才能があったのに、Windowsの劣悪なプログラミング環境(開発ツールの値段の高さもこれに含みます)が、いままで彼らの才能を蝕んできたのだ

 

そう言えば、以前、こんなメールをもらった。

親の反対を押し切ってゲームの専門学校に行くつもりでいるのですが、
やねうらおさんはゲームの専門学校には行かないほうが良いと書かれて
いましたよね?

やはり2年間では短いでしょうか?

いまからでは遅いのでしょうか?

ちなみに私は、プログラムについて何も知りません。

Oh〜!セニョリータ!(誰がセニョリータやねん…) 2年間が短いだなんて言ったことは一度もないぜー、ベイベー(死語) まじめに勉強する気があって、それで、先ほどにも述べたように、非本質的な部分に極力触れなくて済むのならば、2年どころか1年もあればいっちょ前のゲームは作れるぜー。

なんか、いきなり20年ぐらい前の不良中学生みたいな口調になってしまったが、このメールに対する私の回答メールをここに紹介する。

私は、ゲームの専門学校に行くことについて肯定派でも否定派でもありませんし、彼らを見くびったりしたことは一度もないつもりです。(私の文章にそう受け取れる部分があったのならお詫びしますが)

また、ゲーム専門学校からではプロになれないかというとそうでもありません。実際に、ゲーム専門学校を出てきてゲームプログラマーをやってる連中と仕事で関わったこともあります。

私が以前に申し上げたのは、その学習に取り組むスタンスなのです。机に座って講義をただ聞いているだけでゲームが作れるようになるとは決して思わないで欲しいのです。(そんなことを期待してゲームの専門学校に行こう!だなんて決して思わないで欲しいのです)

ゲームの制作もしくはプログラミングとはとてもクリエイティブな作業です。仮に、ある要求仕様通りに作るだけだとしても、それは決して、単純作業ではありません。(特に最初のうちは、格闘だと言っても良いでしょう)

そういうのは、自分で学んで行かなければどうしようもないことなのです。誰かが自分の手を引っ張って新しい扉の向こうまで連れて行ってくれるわけではなく、一歩一歩、自分で階段を作りながら、それを登っていかなければならないのです。

もちろん、それは誰にでも出来ます。個人の能力の格差や資質の問題とは、考えたくありません。あくまで、それはスタンスの違いです。それさえ守れば、誰でもプロになれます。「馬鹿な奴はどれだけやっても無駄」だなんてことは、ありません。

私は、誰しもが無限の可能性を持って生まれてきていると信じています。不幸なことに、自分の才能にすら気づいていない人は多いのですが…。

ただ、ゲームの専門学校に行くことがゲームプログラマーになる唯一の道ではないということを、ふと気がついたらゲームプログラマーになっていた一人の人間として僭越ながら御助言を差し上げたいと思った次第なのです。

自分で昔書いたメールなのだが、いま読み返してみると、なんか少し無責任な気もしないでもない。ちなみに、彼がその後どうなったのかは、やねうらおの知るよしもない。


第7A回 新しいゲームの開発に着手する(アルバイトさん募集) 99/10/3

なんかまた、新しいゲームの開発に着手しないといけないようだ。ちょっと手が回らない。仕事はいっぱい来るし、いっぱいある。手始めに、DDR99のらうーるさんに手伝ってもらおうと思っている。ご存知の方もおられようが、彼は、高校生である。未経験の高校生がプロの業界で通用するというのは、何ともショッキングである。

私自身、衝撃は隠せないでいる。そりゃ自分自身、中学のころからプログラムのアルバイトとかしてたけど…それとは質的にもずいぶんと異なる。(と思う) 高校生が何万本も出るゲームのメインプログラムを組んでいいものか。まあ、プログラムなんて門外漢なゲームデザイナーの人が組むよか、ずっといいのかも知れないけれど(笑)

ちゅーか、このゲーム業界にいると、プログラマーとは一体なんなのか、それすら考えたくなることがある。私が弱小ゲームソフトメーカーとの付き合いが多いからなのかも知れないけれど、ゲームプランナーから、外注のシナリオライターが書いたゲームのシナリオを見せられることがある。このシナリオ、どう思いますか?って。そう言われたってやねぇ、あたしゃプログラマであって、シナリオのことなんかデンデン知らんやん?そりゃ、その昔、ロラン・バルト読んでたし、筒井康隆『文学部唯野教授』とか好きだったけど…なんて思いながら読んでいくと、これまた不条理と不合理な小説なのよ。まあ、制作期間とかそういうのも関係しているからある程度仕方ないのだと思うのだけど、ちょっとプロの仕事としてはお粗末でないのかなー、と思いながら、まあ、自分の意見なんてどうせあまり参考にはされないだろうと思って、思ったまま正直に言ったら、急遽シナリオを大幅修正させるとかで。えっ?私は言ってはならんことを言ってしまったの?私のせいで、世界のどこかでリテイクを食らった外注のシナリオライターの方、おられましたら、やねうらおがこの場をお借りしてお詫びいたしますですよ。

同様になぜか音楽制作サイドからの意見を求められることもある。音楽ゆうてもやね、こちとらプログラマや、ゆうてんのに。もちろん、テキトーなことしか言えないし…ええんでないの?まずいんでないの?とか。最近知ったのだが、私が、まずいんでないの?と言うと、その曲はどうも作り直しになるらしい。ちょ、ちょっと〜。それじゃ責任重大じゃない!私のせいで、リテイクを食らった、ミュージシャンの方、おられましたら、やねうらおがこの場をお借りしてお詫びいたしますですよ。

まあ、プロとアマとの境界だなんてボーダレスなもんで、金をもらっていればそれでプロなのだろうけれど、そういう単純なものでもないようで、外注として高いチャージで働いておられる方々のなかにも、まだ駆け出しの方もたくさんおられるわけで、そんな意味では、素人集団が市販するゲームを制作してええもんかーと思わんでもない。そもそも、やねうらおの意見がこんなに通ってええもんかーとも思わんでもない。プロとしてやってる彼らにしてみれば、やねうらおのせいでリテイクを食らうだなんて、迷惑千万もいいところでありましょう。

そんなやねうらおは、いまだ、ゲーム会社に勤務しているわけでもなく、いまの会社に未練があってすがりついている。坂本龍一のコンサートに関わりたいからだとか、そういうのはないではないけど、何より自分の仕事にケジメをつけてからやめたいと思っている。外でこれだけアルバイトしていて、果たしてそのケジメをつけることが出来るのか、甚だ疑問ではあるけれど、泣いても笑っても来年の3月からはゲーム会社でプロジェクトを引っ張ってかなきゃならんのだからして。

最近、会社(いま勤めているほうね)で話があったのは、ドリカムのコンサートの後ろで踊らせるロボット(?)についてである。音楽に合わせて動く。もちろん、音センサーなんてついていない。あらかじめプログラムされた通りに動くのである。音楽開始後、何msで、この動作をするというようなシーケンスプログラムを使う。いままでたいてい人間がやっていたが、それでも照明等の動きは自動化されており、このようなプログラムで制御している。せっかくだから、このプロジェクトに携わってから会社をやめたいと思うのだけど、このロボット、油圧シリンダーで動くだけに制御は非常に難しいのである。一般的にはフィードバックによってカレントポジションが得て、それをもとに動かす。あるいは、現在位置をフィードバックしてコンパレータを通じて、制御電圧に比例したポジションに移るようなものを使う。ところが、これらは大きさや価格面から、使用できないのではないかということである。うーん。そんなん知らんやん?(笑)

果たして、やねうらおは予定通り、いまの会社を退社できるのでありましょうか…。


第7B回 お悩み相談室1(ある専門学校生の場合) 99/10/5

こんなメールをいただきました。

 うちの専門学校はDENSi系の二年制で、二年の後半にはゼミナールという儀式が行われる。

  つまり二年生の後半の時間割は全てゼミナールで埋まっており、生徒はそこでソフト系とハード系にわかれ、自分の好きなこと(それなりに制限あり)の研究に没頭することが出来る。

  そして最後には外部の方々に発表する仕組み。
 私は友達と二人でゲームを作る予定で、その進行状況を提出したところ、担当の先生に

 M「ゲームならハード系も組み込ませないとなファッファ」
 私「はぁ……」

 といわれ、最初は何だかわからなかったが、要約すると
 「ゲームつくるんならなんか自分も動くバーチャルリアリティ要素追加しろ」ってことらしい。
 ゲームコントローラ作れってことかいな……
 シャレで「DDR作っていいですか?」と先生に聞いてみた。

 M「おーそれはかまわんぞファッファ!
 音とかは生徒の勉強ということで著作権気にするなファッファ!!」

 あっさり通る。でもそれじゃあ何の工夫もない、ただのプログラムなだけでそれなりのオリジナリティあふれるものにしようと決意。とりあえずDDR作るとしてコントローラ。相当の覚悟を決めたが、そういう場合、コナミのものを使用していいとのこと。どこまでいいんだか……

 ゼミナールの目的は市販してもおかしくないものを作るのがモットーなわけでダイレクトパッドプロのようなプログラムを作ろうとしたところ、

 M「それじゃあゼミナールにならないぞファ!windowsゲームコントローラから読み出すんじゃなくてプログラムからmidiポートならmidiポート、パラレルならパラレルに直に読み出すようにするんだファッファ!!」

//////////

 こういうわけです。語尾はファントムのファです。
 先生は***出身で怖くて逆らえません。

 そういうwindowsサポートしているものをつかうなっていうんなら、何でVisualC++のMFCは許せるのかと疑問にもなります。

 まぁそれぐらいのことを研究して出来てこそゼミナールだと思うのですが、 やっぱゲームコントローラを使わないってのはちょっと引っかかります……

 下手に反抗しようなら
 M「おまえそんなこというんなら俺の消火器しゃぶれファッファ!」

 なんて事になりかねないので(***は**が多いらしいので)

 やねさんはどうお思いでしょうか?
 やはりそれくらいできてナンボでしょうか?何か自分ナマケモノ……

 あーん、やっぱそれを覚えて知識が広がったとしてもまだ……ひっかかる

すでに、ご自身でそれなりの結論を出されているようで、こういうのちょっと茶化しように困ります。(茶化さんでええって!>俺)

MIDIポートやシリアルポートから直にデータを読み出すことにどれほどの意味や価値があるのか、私にも理解しかねるものがありますが(笑)、それもひとつの経験ではないかなーと思います。どうも、技術ってのは、必要に迫られたときにしか吸収できないのではないか?と思っています。これも千載一遇のチャンスだと思って、トライされれば良いでしょう。もっとも、トライしなかったからと言って、どうなるというものでもありません。言ってみればそれは、大学の選択科目みたいなもので、最低限、プログラマとしてやっていくのに、トータルで何単位の単位(知識・経験)が必要というのはあるでしょうけれど、これとこれが絶対出来なくてはならないという線はどこまで行っても見えてこないからです。逆に、これとこれが出来れば、十分であるというラインもありません。だから、そう。若者よ、いつもgreedy(貪欲)であれ!


第7C回 How to use STL on Visual C++5.0(STL教えます) 99/10/6

VC++5.0でyaneuraoGameSDKがコンパイルできないということで、VC++5.0をほじくり返し、インストールして、自分でやってみた。VC++5.0の段階でSTL自体は実装されているし、テンプレートの機能もあるようなのだが…。

#include <list>
using namespace std;

class ABC {
      int x;
      int y;
};

typedef list<ABC> ABCArray;

ABCArray abcarray;

とりあえず、こんな感じのプログラムを組むと、コンパイルエラーが30個近く出る。エラー内容も、宇宙人の言葉のようで、何を言っているのかさっぱりわからない。理解不能である。だいたい、こんなエラー内容ならば、真面目に読む価値もない。なにしろテンプレート君にしてみれば、いつものことなのだから…とか思っている。

まあ、やねうらおも、こんな調子だから、知らない間にまわりの人間が順番にUFOにキャプチャーされて、洗脳チップを脳に埋め込まれ、気がつくと親や兄弟までもが宇宙人の操り人形にされていたとしても、まーいつものことやからな、とか案外自分がUFOのなかで脳をかっぽり開かれて、洗脳チップを入れられるそのときまで、続のほほんとしてるんだろうけど。(それはサントリーのお茶や)

そんなことはどうでもいいのだが、結論から言うと上のプログラムは比較演算子==,<,!=,>を定義してやる必要がある。前の2つは、class ABCのpublicメンバとしてbool operator ==(const ABC& s) { return s == *this; }みたいな感じで。後ろの2つは、グローバルスコープでbool operator !=(const ABC& s,const ABC&t){ return s!=t; }みたいな感じで、である。

なぜこのような比較演算子の定義が必要なのかよくわからないのだが、おそらくVC++5.0のテンプレートの展開の甘さに由来するものではないかと思う。本来、classに対して、ディフォルトで比較演算子がクラスメンバのビット列比較として定義されているはずだから(それが証拠に、上のreturn s == *thisの部分はvalidである)、これを定義しておかないとエラーになるというのは、どうも理不尽なような気がする。

そんなわけで、組み込み変数型のint、long、そして、なんとか型へのポインタなどのオブジェクトに対するコンテナクラスは問題ないが(よーするにlist<int>とかvector<sprite*>だとか)、それ以外のユーザー独自のclassに対するコンテナクラスでは、上の4つの比較演算子の定義が必要なようである。(VC++5.0での話。VC++6.0では改善されている)

しかしよー、たったこれだけのことでエラー28個。yaneuraoGameSDKに至っては、VC++5.0でコンパイルすると、CWinHookに対して、これ参照してるファイルすべてからこのエラーが出るもんで、エラーが300個ぐらい出るんよ。それ見てある人なんかは「STL使うのやめましょーよー。いまなら昔のソースも無傷で残ってますし…」と嘆きのメールを送ってきたぐらいである。待て待て!!STLのエラーの数と難解なメッセージに踊らされてはいかん!こういうのは、ビビった方の負けじゃ。向こうがわけわからんことゆうてきたら、こっちもパペポピパーとか、わけわからんことゆうて返したったらええんじゃ!(それで何の解決になるゆーねん>俺)


第7D回 VisualC++のバグ(新しいのん買えっちゅーことか?) 99/10/24

STLのコンパイルがらみで引っ掛かって以来、MicrosoftのKnowledge Database(特にサポート情報≒バグ情報)をしょっちゅう参照するようになった。VisualC++5.0のServicePackで修正されている内容を見たりすると、よーこんなカスなコンパイラを金とって世に出しとるなーと思う。return文で値を返すときにインクリメントつかったらバグるだとか、なんか自分がプログラムするときに、何気にやっていそうな内容がやまほど書いてある。こんなのを見ていると、使うのさえ怖くなってくる。

ちなみに、第7C回で書いたSTLのtemplateのバグは、Visual C++5.0のServicePack3で修正されている。(ServicePack2では不可) ところが、yaneuraoGameSDKをコンパイルするには、Visual C++5.0には、もうひとつバグがあって、関数ポインタvectorは、iteratorを使えないのである。つまり、

    vector<void (*)()>::iterator it;

これが、コンパイルエラーになるのである。そこまで行くと、もう知るかー!と言いたくなるが、おそらくテンプレートの展開をするときの構文解析の甘さが原因だろう。こいつは、

    typedef void (*FUNC)();
    vector<FUNC>::iterator it;

とやれば、コンパイルは通る。さらに、今度は、苦労して書き直したファイル入力部が、内部コンパイルエラーとかで落ちる。なんじゃいな、そりゃ!調べていると、

    string name = lpszFilename;

と直接LPSTRからstring型の変数に代入している部分がまずいようである。(内部エラーにならないこともある) どうも、こいつの暗黙のデストラクタ付近で内部エラーで落ちるもんで、特定するのに時間がかかったわい。怖いから、すべて

    string name;
   
name = lpszFilename;

と書くことにした。これで、ようやくコンパイル成功である。

まー、Visual C++5.0はバグだらけだから、バグだらけのソフトウェアしか構築できないとか、そういうことを言いたいのではない。OSがバグだらけでもシステムは今日も元気いっぱい動いているのが工学の世界なのだ。コンパイラがいかに腐っていようが、それはバグのないアプリを書けない理由にはならない。論理に欠陥があろうと有用な理論は構築できるのだ。そこを勘違いするなよ、と自分によく言い聞かせたやねうらおであった。


第7E回 再帰について考える(なんでないんやろ?) 99/10/27

フォルダ検索のためのclassを書いていたのだが、WindowsのAPIには、wildcard付きの比較関数が無いようである。findfirst等で、wildcard付きで検索できるのに、その肝心のmatchingルーチンが公開されとらんっちゅーのは、どーゆー骨茶!(なんや、このやる気のない変換は…)

そう言えば確か、Javaでは、WildcardExpressionとかゆーclassがあったように思う。なんかそう考えると、こんなもんぐらい、なんでC++の標準ライブラリとして用意してくれへんのかなーとか思わんでもないのだが、そんなことを言ってても仕方ないんで、サクっと組んでみることにした。(所要時間30分)

bool IsMatch(LPCSTR it1,LPCSTR it2){
    while (true){
        if (*it1 == '*') {
            it1++;
            do {
                if (IsMatch(it1,it2)) return true; // 一回でも一致すればtrue
            } while (*(it2++)!='\0'); 
            return false; // すべて一致しないならばfalse
        }
        if (*it2 == '*') {
            it2++;
            do {
                if (IsMatch(it1,it2)) return true; // 一回でも一致すればtrue
            } while (*(it1++)!='\0'); 
            return false; // すべて一致しないならばfalse
        }
        if ((*it1 != *it2) && (*it1 != '?') && (*it2 != '?')) return false;
        if (*it1=='\0' && *it2=='\0') return true; // 一致した
        if (*it2=='\0' || *it2=='\0') return false;
        it1 ++;
        it2 ++;
    }
}

手抜きで漢字のチェックはしていないが、"abc*fghi"と"ab*def*h?"というように、比較する両側の文字列にいくつ'*'や'?'を使用していても、再帰を利用してうまく一致判定が出来る。

最近の若いプログラマは、どうも、この手の再帰処理をうまく書けないようである。確かに使う機会は減ったような気もするが、こんな程度のプログラムがサクっと作れないのなら、プロ失格だろう。

ちょうどいい機会なので、身内のプログラマ(5名/全員プロ)に、やってもらった。1時間以内に、僕と同じような答えに辿りついた人は、一人だけ。それから不都合があるものの、2時間ほどかけて一応は動くものを作れたのが一人。あとの三人は、再帰を知らないのか、思いつかないのか、ほとんどお手上げ状態であった。まったく、なんちゅー、サブーイ状況なんや!あんたら、金もろてんねんから、教科書に載ってるレベルのプログラムぐらいサクっと書いてーやー!(笑) とは言うものの、仕事でプログラムやってると目の前の仕事に追われて、勉強どころでないのかも知れない。それは、僕も同じなので、まあ頑張れよーとか言って、彼らの肩を叩いて励ましたのであった。


第7F回 錬金術について考える(謎) 99/10/28

今回は、錬金術について考えるのだ。と言っても、化学的な話ではない。無から有を生み出すことが可能かということについてである。なんじゃいそりゃ!と突っ込む前にちょっと考えて欲しい。

    x  =  y;

というC言語のプログラムがあるとする。これは、言うまでもなく代入を意味する。この代入っちゅー概念がやねー、プログラミングをやってみたろかいなーとか思ったときに、最初に出てくるややこしい概念なのではないかと思うのだ。「代入」、これは、直接的には、値をコピーすることを意味する。コピー元は副作用を受けない。つまり上の例ならばyの値は変化しない。xにyの値がコピーされる。それを代入と呼ぶ。そんなことわかってるって?はいはい。そうでしょうとも。

しかし、僕に言わせれば、この代入という行為が無から有を生み出すカラクリその1なのではないかと…。

よく考えてみて欲しい。代入は、日常生活で出てこない概念である。財布から金を払えば、財布の中身は減る。財布の中を変化させずに、お金だけを外に出すことが出来るというのが、この代入という行為なのだ。実は、とっても不思議なのだ。

僕は、この代入の有用性を認めながらも、この代入がなかったら、どんなにええのもんかーと思うこともある。代入なしに、どうやってプログラムできんのや?と言う人もいるだろう。たとえば僕がかつて愛用していたPrologなんかは、代入というものが存在しない。しかし、まったく代入なしにプログラムできるわけでもないから、Prologの場合、カットオペレータを駆使して、擬似的な代入を実現するのだが、あのへんがPrologの嫌らしさであり、醜悪とも言える部分であるが…代入を使わないことには、Prologでは実用になるプログラムは書けない(と思う) 代入なしではある規模のソフトウェアは作れないという現実を反映しているのかも知れない。

なぜこんなに代入にこだわるかというと、代入が関数性をぶち壊す要因たりえるからである。

    int f(void){
        static int x=0;
        return x++;
    }

このf()は、数学的な意味での関数ではない。この関数が“評価”されるごとに、インクリメントされるからである。(インクリメントは、x = x + 1;の意味であり、これは立派な代入である) 数学的な関数としての性質が保てないのである。この意味で、代入を採用している関数型言語は、純然たる関数型言語ではない(と思う) この代入という行為が、プログラムの解析や検証を非常に困難にしているのだ。

たとえば、

    void f(void){
        for(int x=1234567;x;x--) ;
    }

このプログラムは停止するか?まあ、正の整数から1引く作業を繰り返すわけだから、いつか0になって停止するのだが、では、x--がx-=3ならどうか?これを、実際にプログラムを実行することなしに判定することが可能だろうか?実際、1234567は3の倍数ではないから停止しないのだが、この場合、倍数、あるいは剰余という概念が必要となる。もう少し複雑な式の与えかたをすれば、もっと高度な概念が必要となる。さらに言えば、一般的な停止問題は解決できないのである。(ゲーデルの不完全性定理が作用していると思いねぇ!) これは、代入が生み出す悲劇であり、数学的にクリーンな議論をしにくくさせる要因でもある。

まー、そんなことはどうでもいいのだ。(どうでもええんかいな)

やねうらおも、プログラムをやり初めて、かれこれ20年近くになろうとしている。そして、数年ごとにプログラミングのパラダイムについて、じっくり見つめなおしたり考えたりすることがある。そんななかで、わかっているようで、一番わかっていない概念が、代入ではないかと思うようになったのだ…。「何を馬鹿なことを言ってるんだ」と思うか、「へーこんな考えかたもあるのか」と思うかは個人の自由だが、出来ることならここから何か発展させて欲しいと思う。


戻る