Delphi で学ぶ古典ゲームの仕組み 第１回：歴史（ハードとゲームの関係）

# はじめに

最近は様々なゲーム開発環境があり非常に簡単にゲームを作成できます。
しかし、その結果ゲームの製作についてあやふやな知識のままゲームを作成する人も多くなっています。
たとえば「フレーム」や「ゲームループ」といった基礎的な知識が無いためコミュニケーションに問題が発生することもしばしばです。

ということで、このシリーズでは昔ながらのゲームの製作方法を解説します。
昔ながらといいつつも現代のゲームの基礎にもなっている事です。
基礎を押えることで現代のゲーム製作環境の事もより深く理解できるようになります。

# 全体の目次

まずは全体の目次です。

1. [歴史（ハードとゲームの関係）](https://qiita.com/pik/items/2ee126169a76214f8a22)（この記事です）
1. [ゲームループを作ろう](https://qiita.com/pik/items/fa80fa4b942bb6c2a79a)
1. [オブジェクトを動かしてみよう](https://qiita.com/pik/items/1c61fda562d38e69a12e)
1. [入力を受け付けよう](https://qiita.com/pik/items/b34a9b2030f09c11825e)
1. [コリジョン判定を作ろう](https://qiita.com/pik/items/529812e304eb7db974e5)
1. プレイループを考えよう（終わり）

では、さっそくコンピューターゲームの歴史について紹介します！

# コンピューターゲームの黎明期

ゲームはコンピューターが誕生してすぐに製作されました。
どれくらいすぐかというと、なんと「[EDSAC](https://ja.wikipedia.org/wiki/EDSAC)」という最初期の真空管でできたコンピューターで上で誕生しました。それが 1952 年の [OXO](https://ja.wikipedia.org/wiki/OXO) という三目並べゲームです。
ただ当時はゲームは人工知能の研究としてだったので厳密にはゲームとは言えないかもしれません。
OXO は EDSAC に搭載されていた「横35ドット × 縦16ドットのブラウン管」に表示されていました。

そこから [Spacewar! (1962)](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%A6%E3%82%A9%E3%83%BC!) や初めて商業的成功を収めた [PONG (1972)](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%B3_(%E3%82%B2%E3%83%BC%E3%83%A0)) など様々なゲームが出ました。

# ホビーコンピューターとゲーム
1980年代から「マイコン」と呼ばれる[家庭用ホビー向けパーソナルコンピューター](https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%93%E3%83%BC%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3)が発売されます。
シャープから MZ や X1, X68000 シリーズ、富士通から FM TOWNS、ソニーから SMC-777、ソード M5 やバンダイ RX-78 GUNDAM などなど様々なメーカーからマイコンが発売されました。
NEC からは [PC-8001](https://ja.wikipedia.org/wiki/PC-8000%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA) が発売され大ヒットになります。
その後、PC-6000, PC-6600, PC-8800 (略称：ハチハチ), PC-9800 (略称：キューハチ) シリーズが発売されます。
そして、PC-9800 シリーズは国民機と呼ばれるほどのシェアをもち、NEC がマイコン市場を席巻しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/26dcd241-ae37-28af-bfff-74526878a322.png)
図１．1989 年の各社のシェア（[Wikipedia より](https://ja.wikipedia.org/wiki/PC-9800%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA#/media/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Usage_share_of_personal_computers_at_home_in_Japan_as_of_1989.png)）
（Epson は 98 互換機を作っていたので実質的なシェアは 50% 以上あったことになる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/da6d92ef-6b03-6e87-4e5c-c9e1e72bab0e.png)
図２．PC-8001（[Wikipedia より](https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%93%E3%83%BC%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3#/media/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Nec_PC_8000_series.jpg)）
(CC 2.0 表示：Tom west user of flickr - https://www.flickr.com/photos/tomwest/274218826)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/4e8e3eab-8225-5f11-e67d-5d47c2549c8d.png)
図３．PC-9801 VM (後の 98 シリーズの原型となったモデル, [ブログより](https://cooblog.blog.ss-blog.jp/2020-09-23)）

:::note info
2015 年に休刊した「[マイコン BASIC マガジン](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%82%B3%E3%83%B3BASIC%E3%83%9E%E3%82%AC%E3%82%B8%E3%83%B3)」もこの頃の創刊だったため「マイコン」と銘打ってあります。
略称は「ベーマガ」でマイコンは入っていませんでしたが…
:::

では「マイコン」は何に使われたかというと、趣味のプログラミングと「ゲーム」が大きな利用用途でした。
「マイコン少年」という言葉もありました。マイコン上でプログラムを組んで自分でゲームを作りベーマガに投稿する、またはベーマガに載っているプログラムを入力してゲームを楽しむ、そんな大人から見てコンピューターを使いこなしている少年少女たちをマイコン少年と呼んでいました。

つまり、プログラムとゲームは非常に近いところにありました。
そうしたマイコン少年達がゲームプログラムを売ったりゲーム会社を立ち上げたりしてゲーム市場が形成されていきました。

:::note info
マイコン各社のハードウェアは、それぞれに全く互換性がありませんでした。
同じ規格でハードを作り互換性を持たせようという規格が「[MSX](https://ja.wikipedia.org/wiki/MSX)」でした。
MSX は米マイクロソフトとアスキーが制定した規格で、MSX 規格のハードウェアも多数発売されました。
:::

# VRAM
VRAM とは Video RAM の略称です。
機種によって異なるのですが概ね VRAM とディスプレイは連動しており、ここに書き込まれた値が画面に表示されるようになっていました。

現代の GPU では複数の VRAM を持っていますが当時はメモリが非常に高価なため VRAM を持たずに直接コントローラーに書き出すハードウェアもありました。
そんな中 PC-9801 は VRAM を２枚持ちバンク切り替えで表示を切り替えられました。
表示されていない VRAM に次の画面を描き、表示される VRAM を「あるタイミング」で切り替える事で画面が乱れたりせず美しく描画できました。

この「あるタイミング」が「VSYNC 割り込み」です。

# VRAM と VSYNC 割り込み
VRAM に色情報を書き込むとディスプレイにその色が表示されます。

具体的な仕組みは
1. プログラムが VRAM に色情報を書き込む
1. VSYNC 割り込みのタイミングで表と裏のバンクを切り替える
1. ディスプレイコントローラが VRAM の情報を読みながら描画していく
1. 最後まで表示し終わって左上に戻る瞬間に VSYNC 割り込みが発生する
というものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/ad616a88-d97f-296d-0ba9-6b07c72458b1.png)
図４．VSYNC割り込みのループ

VSYNC (V-Sync とも) とは日本語では「垂直同期信号」といい、今の言葉で言うと「リフレッシュレート」のことです。

:::note info
「割り込み」とは、何らかの状態によって引き起こされるプログラムの実行位置の変更です。
今風にすると「イベント・ドリブン」といえるかも知れません。

割り込みが発生すると

1. 現在実行中のプログラムを中止（レジスタなどをスタックに積む）
1. 割り込みベクターに書いてあるアドレスに飛ぶ
1. 割り込みプログラムを実行する
1. 実行終了で（レジスタなどをスタックから読み込んで）元の処理に戻る

という処理をします。
:::

そして、VSYNC 割り込みのプログラムは自由に変更できました（割り込みベクターのアドレスを書き換える）。

この辺りの技術の詳細は下記のブログに非常に詳しく書いてあるのでご一読をオススメします。
https://www.wizforest.com/OldGood/ntsc/
https://yosshin4004.github.io/memo/vsync/index.html

VSYNC 割り込みはその性質上定期的に発生します。

そこでゲームの処理を VSYNC 割り込みのタイミングで行うというアイデアが誕生しました。
なぜ VSYNC 割り込みでゲームを処理する必要があったのでしょうか？

# ゲームは全て同期処理

アクションゲームやシューティングゲームの場合、ゲームプログラムとは物体の運動を定義する作業です。
つまり、ある物体が ```t``` 秒の時の座標 ```Xt, Yt``` を導出する作業です。

具体的に、弾と敵が衝突する処理を考えましょう。
弾と敵の運動を示す方程式を書いて座標を求めます。
今回はどちらも等速運動をするものとします。

**弾**
* MP: 弾の座標
* MP0: 弾の初期座標
* MV: 弾の速度 [pixel/msec]
* t: 時間 [msec]

としたとき、MP は次のようになります。
```delphi
MP = MP0 + MV * t
```

**敵**
* EP: 敵の座標
* EP0: 敵の初期座標
* EV: 敵の速度 [pixel/msec]
* t: 時間 [msec]

としたとき、EP は次のようになります。
```delphi
EP = EP0 + EV * t
```

この２つの方程式－連立方程式を解いて解がある（交点がある）なら、ある時間 tx に衝突するということが解ります。逆に解がないなら弾と敵は衝突しない事がわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/94474f34-deff-69b0-af0b-bc2e6cb6fb61.png)

ここで、それぞれの t が別々の t だったらどうなるでしょう？
たとえば、弾と敵が別々のタイマーを使って動いていた場合、別々の時間軸で動作するため交点を求められません。
それぞれ別の t を使うので連立方程式が成立しないのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/e1e3cde0-1095-1ce1-d873-d607ce4b34f3.png)

VSYNC を使えば t が同じ時間軸になるため、式が成立し計算できるようになります。
そのため、ゲームでは VSYNC 割り込みに処理が書かれました。

# リフレッシュレートとフレームレート

VSYNC の所でリフレッシュレートのことと書きました。
例えばリフレッシュレートが 60 [Hz] のディスプレイは 1 秒の間に 60 回画面が更新されることを示しています。
つまり 16.6 [msec] に１回画面が更新されます。

これに対して、フレームレートとは１秒間に用意できる画面の枚数を示します。
例えば、60 [fps または Hz] とは１秒間に 60 枚画面を用意できるということです。
つまり、16.6 [msec] に１回画面を用意できます。

例に上げたリフレッシュレートとフレームレートの値がそっくりですね！
これは偶然ではありません。
リフレッシュレートとフレームレートがあっている場合最も効率よく画面を更新できるのです。

```
１フレーム＝１リフレッシュ
```

となった時、もっとも更新回数が多くなるのは当然です。

もしもフレームレートが 30[fps]　だった場合は

```
１フレーム＝２リフレッシュ
```

となり、60 [fps] の時に比べ画面の更新頻度が半分になってしまいます。
これがさらに 15[fps] となると…

```
１フレーム＝４リフレッシュ
```

となります。

このように１リフレッシュの間に画像が用意できなかった場合、その間は同じ画像が表示され続けるため画面はガックガクという状態になります。いわゆる「フレーム落ち」という状態です。
画面上に大量の敵や弾が出てくると画面がガックガクになるのは、大量に出てきた敵や弾の計算が終わるまで画面を描画できないためです。

まとめると以下のようになります。

| | 説明 | 単位 | 依存対象 | 具体的な対象 |
|---|---|---|---|---|
| リフレッシュレート | 画面を更新する周期 | Hz | ハードウェア | ディスプレイ | 
| フレームレート | 画面描画用画像を用意できる周期 | fps または Hz | ソフトウェア | ゲームプログラム |

:::note info
フレームレートの「フレーム」とは、元々は映画用語でフィルムの１コマ分の事を言います。
ゲームで良く使われる fps (Frame Per Second) も映画用語の「フレームが１秒間に何枚通過するか」が元になっています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/a67fbf35-4abb-f816-72a7-3ecc32bef64e.png" width=160>
:::


# ハードとゲームの関係

ここまで見てきたように、ゲームはハードウェアとともに進化してきたことが解ります。
また、VSYNC で同期を取ったり、ゲームはハードウェアの特性を上手く利用してきました。
ゲームがハードウェアの性能や特性に影響されるなら、ゲーム専用のハードウェアを作れば良い！という発想に行き着くのは自然な事です。
そうして、ゲーム専用のハードウェアを積んだアーケードゲーム機や家庭用ゲーム機が登場することになります、が、それはまた別のお話。

[第２回につづく](https://qiita.com/pik/items/fa80fa4b942bb6c2a79a)