SQLDoom
出典: cdn.mos.cms.futurecdn.net

SQLDoomはゲーム処理をデータベース内で実行

Lukas Vogel氏の「SQLDoom」は、1993年のゲーム「Doom」のゲームロジックと描画処理をSQLで実装し、CedarDB上で動かすプロジェクトです。Pythonクライアントはキーボード入力や時間管理、画面表示を担当し、ゲーム状態の更新と画面生成はデータベース内で処理します。

ゲームロジックはオリジナルと同じ毎秒35回の周期で動きます。一方、描画はゲーム処理から切り離され、クライアントは必要に応じてフレームを取得でき、ゲーム更新の間はカメラ位置を補間します。

ゲームのマップやオブジェクトを含むWADファイルは、頂点、線、領域などのデータから構成されます。Vogel氏はこれらをデータベースのテーブルへ取り込む処理を約1,000行のPythonで作り、Doom 1全体の読み込みは自身のノートPCで約18秒だったと説明しています。

ゲームロジックは約5,900行のSQL

ゲームロジックは約5,900行のSQLで構成され、元のCソースコードの約9,000行より少ないとVogel氏は報告しています。SQLでは、条件に合う行をまとめて更新する「UPDATE ... WHERE」を使えるため、エンティティを一つずつループで処理する必要がない場合があります。

毎秒35回のゲーム更新では、1回の処理に使える時間は約28.6ミリ秒です。Vogel氏によると、目覚めている敵が6体の一般的な更新は平均2.15ミリ秒で、敵46体が動くE4M1の最も重い更新でも10.45ミリ秒でした。

処理は移動、敵の状態更新、武器やダメージの処理など複数の段階に分かれています。敵の状態遷移もSQLで記述され、たとえば敵の体力が最大体力を大きく下回る場合に、死亡時の状態を分岐させます。

画面描画にもSQLを使用

SQLDoomの描画処理は約1,300行で、89個の共通テーブル式(CTE)に分かれています。CTEは、クエリの中で一時的な結果を段階的に扱う仕組みです。

壁の前後関係を決めるため、Doomの二分木による空間分割(BSP)の経路を読み込み時に計算し、並べ替えに使える値として保存します。描画時にはその値を使って壁を前から順に処理し、SQLの「ORDER BY」で表示順を決めます。

床と天井の描画は、元のDoomが使う処理をSQLへそのまま置き換えにくい部分です。Vogel氏は、画面上の領域を並べて処理する方法を採用しました。描画負荷は場面によって変わり、同氏のRyzen 7搭載ノートPCでは通常約60 FPS、忙しい場面では35 FPSまで下がることがあります。

DoomQLからの進展とマルチプレイ

前作のDoomQLは、レイキャスティングを使ったASCII表示で、Ars Technicaはその見た目を「Wolfenstein 3D」に近いと評しています。SQLDoomではBSPによる描画を実装し、テクスチャや壁の角度、床の高さの違いを扱えるようになりました。

Ars Technicaによると、SQLDoomはゲームロジックも含めてオリジナルに近いプレイを目指しています。

マルチプレイは最大4人のデスマッチに対応し、ゲーム更新をトランザクションとして実行します。Vogel氏は、更新を開始してから確定するまでの状態を一括で扱えるため、プレイヤーごとに更新途中の状態が見えることを防げると説明しています。プレイヤーの操作は用意された関数を通じて受け付け、テーブルへの直接アクセスは制限しています。