一般受けしそうな話は尽きた(笑)
でも、実は僕としてはここからの話の方が書きたいかも。
プログラマしか楽しめない技術話です。
手相うらないは、System 32 で作られました。CPU は V60 。
実は、大学時代の研究室の教授が設計した CPU です。
まさか就職して、恩師の作った CPU でプログラム組むとは思ってなかった。
手相占いのプログラムは、すべて V60 アセンブラで書かれていますが、「オブジェクト指向」でした。
当時の僕は、アセンブラとC言語、それに AWK と BASIC と…まぁ、手続型言語は使えましたが、オブジェクト指向は理解できていませんでした。
と言っても、オブジェクト指向のことは知っていて、それを扱える処理系を触ったことがなかっただけ。
その一方で、「オブジェクト指向はプログラムスタイルであって、言語ではない」という話も読んでいました。
#Oh!X で、1987年12月から、「オブジェクト指向のゲームプログラミング」という連載があったそうです。
ただ、僕はこれは読んでいません。Oh!X 買い始めたの、1990年ごろからなので。
でも、後の記事の中に「過去の連載にあった」「アセンブラでもオブジェクト指向は出来る」と書かれていたのです。
頭では理解できました。
たとえば、再帰処理を行うのにローカル変数は必要ありません。BASIC でも再帰は行えます。
でも、多くの人が BASIC では再帰はできない、と思っています。
その理由は、再帰を正しく理解できていないから。それだけです。
#再帰って、処理の中から自分自身を呼び出す処理方法。C言語では再帰が「簡単に」できます。
でも、Cでないとできない、と思っている人が多数います。簡単でないだけで、BASIC でもできるのに。
そして僕はこの時、オブジェクト指向を正しく理解できていませんでした。
「オブジェクト指向言語を使わないでもオブジェクト指向に出来る」は、頭で理解できてもどうやればよいのかわからなかったのです。
その答えが目の前にありました。
すでにアセンブラでオブジェクト指向を行うための「フレームワーク」は組みあがっていて、そこに新たなプログラムを追加していけばいいのです。
#フレームワーク、なんていうとかっこいいけど、前回作である「スターライトフォーチュン」の部分流用です。
もっと言えば、System32 の初期の作品から、プログラムは脈々と流用され続けてきたのでしょう。
それまでオブジェクト指向がどうも理解できていなかったのですが、非常に低レベルなアセンブラで経験したため、その後は C++ を見ても Java を見ても、内部でどのように処理しているのか…が理解できるようになりました。
C言語覚えた時も、アセンブラでどのように出力されるかを見て「理解」したのだよな (^^;
どうも僕は、アセンブラまで一度落とさないと理解できないようです。
それまで、僕は「ベーマガで覚えた」スタイルでゲームを作っていました。
敵の数だけ座標などの変数を用意し、自分の座標の変数と、自分の撃った弾の座標の変数を用意する。
それぞれのキャラクターが「生きている」か「死んでいる」かを判断するフラグもあり、それらを見ながら、座標を操作し、それぞれを表示し…
というのを、ループ内で延々と書く。
これでゲームは作れます。
ベーマガに載っていたゲームなんてほとんどこうだし、昔は市販ゲームでもこうでした。
でも、手相で使ったフレームワークはそうではありませんでした。
キャラクターは全て「オブジェクト」として扱います。
オブジェクトは、大きく分けて画面表示を伴うものと、そうでないものに大別されます。
各オブジェクトには、64バイトのメモリ空間が与えられています。
表示キャラクタの場合、座標データや、表示キャラクタの番号、表示優先順位などはこのメモリの、決まった位置に置かれます。
残りのメモリは自由に使って構いません。
キャラクターの移動速度だったり、向きだったり、ゲームに必要な内部的な値です。
各キャラクタを「うごかす」ためのプログラムは、実は64バイトのメモリ空間内の、特定位置に開始アドレスが書かれています。
そして、そのアドレスは毎フレーム(1/60秒)毎に、必ず呼び出されます。
呼び出されたら座標などを移動し、最後に「表示ルーチン」を呼び出します。
先に書いたように、表示パラメータは 64バイトのメモリ空間内の固定位置に入っていて、表示ルーチンはこれを解釈して表示を行います。
敵でも自機でも弾でも、「処理した後で表示ルーチンを呼べばよい」という流れは同じ。
この「64バイトのメモリ空間」は、処理プログラムが呼び出される際に、アドレスがレジスタのうち1本に入れられています。
なので、このレジスタからの相対アドレッシングを行えば、簡単にアクセスできます。
敵が複数表示されるときも、プログラムは一つだけで大丈夫。
メモリ空間が自動的に変更され、同じプログラムを繰り返し呼び出すことで、複数の敵を処理できます。
「ほぼ共通だけど、一部違う」ような処理が必要な場合、違う部分の処理だけを分離しておき、「処理アドレス」をメモリ空間内に書いておきます。
処理プログラムの中で、そのアドレスにジャンプするようなプログラムを書いておくことで、共通部分は使いまわしたままで、キャラクタごとに違う処理を行えます。
ベーマガ式にプログラムを組んでいると、キャラクタごとに「生き死に」の判定が必要です。
しかし、オブジェクトで処理する場合は、死んだキャラに関してはメモリ空間を開放してしまいます。すると、処理プログラム自体が呼び出されなくなります。
新たなキャラを生成する場合は、メモリを確保し、適切な初期値を書き込みます。
これで、以降は処理プログラムが呼び出されるようになります。
ちなみに、64バイトのメモリ空間のうち、最初の 8byte は、管理用の固定で使用されていました。
まず、「次のメモリ」を示すためのアドレス 4byte 。そして、「処理アドレス」を示すための 4byte 。
これにより、次々と「次のメモリ」を探し出し、処理アドレスを呼び出すのです。
メモリ空間の開放や、新たなメモリ確保は、次のメモリアドレスを書き変えることで行われました。
#いわゆるチェーンリスト構造。
この環境でプログラム組むのが、とにかく楽しかった。
ゲーム作成経験者じゃないと分かってもらえないかもしれない。
ベーマガ式にプログラム組んでいくと、だんだん「管理しないといけない変数」が増え続けてしまって、規模が大きくなるにつれて辛くなるのね。
それを、すべてのキャラや処理をまとめて「オブジェクト」と捉え、その処理ルーチンを用意しただけで、変数管理から解放される。
オブジェクトの生成や破棄など、いくつかのルールを守っているだけで、後は処理するプログラムだけに注意を払えばいいんです。
後の話ですが、サターンで使用されたSGLも、C言語のライブラリとして作られていましたが、同じような構造を前提として作られていました。
ところが、このフレームワークを「オブジェクト指向」だと気づいてない人の方が多かったようなのですね。
ゲーム開発の現場って、みんなゲーム好きだけど、それほど言語マニアは集まってません。
C言語しかできない、アセンブラしかできない、とかそういう人が多い。
ずっとのちの話になりますが、ある先輩が「C++勉強してみたら、いつも使っている環境をプログラムしやすいことに気付いた」と言うのです。
「オブジェクト指向とゲーム制作は相性が良い」と。
僕としては、オブジェクト指向「言語」を使っていなかっただけで、作り方はオブジェクト指向だと思ってました。
だから、これは発見でもなんでもないのだけど、その先輩もゲーム一筋の人で、言語にはそれほど興味がなかったので大発見だったみたい。
ただ、この先輩すごいプログラム能力の持ち主で、「これはいい!」って、一気に必要なライブラリ全部 C++ で作っちゃったのね。
それで、部内で C++ の布教活動初めて、自分のプロジェクト内は C++ で開発することにしちゃった。
行動力と実力が伴っていました。素晴らしい。
同じテーマの日記(最近の一覧)
関連ページ
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |