第1章
このデモとは
「あの1993年の DOOM を、プラグインもエミュレータも使わず、素のブラウザとコードだけで動かせるの?」に、動く実装で答えるサンプルです。
このデモは、Babylon.js ファミリーの WebGPU 専用ランタイム Babylon Lite の公式リポジトリに含まれる、DOOM の再現です。ゲームの中身が入った WAD ファイル(バイナリのデータ塊)をネット越しに読み込み、その中の地図・テクスチャ・スプライト・音を自前のコードで解析して、3D の迷宮として描き、モンスターを動かし、銃を撃てるところまで作り込まれています。
各ファイルの冒頭には「オリジナルの DOOM エンジン(GPL)のソースは一切参照・複製していない」と明記され、公開仕様(Doom Wiki/Unofficial Doom Specs)だけを頼りにゼロから書き起こしたことが宣言されています。読み込むデータも、権利的にフリーな互換 IWAD Freedoom(freedoom1.wad)。だから安心して中身を読めます。
プログラムとしての見どころは、次の3点です。
WAD の12バイトのヘッダから、地図の頂点・線・区画まで、生のバイト列を1つずつ意味に変えていく“データ考古学”。フォーマットの教科書です。
DOOM 特有の、距離でカクッと帯状に暗くなるあの陰影。RGB を混ぜるのではなく、パレット番号を COLORMAP で引き直すという当時の手法を、そのままシェーダで再現します。
敵の見た目も行動も、コードではなく表(テーブル)で定義。「型 → 状態 → 行動」の3段構えで動く、DOOM 名物のアクターシステムを移植しています。
第2章
あそびかた
コードを読む前に、まず走り回るのがいちばんの近道です。操作はオリジナルの DOOM に沿っています。
babylonjs.com のライブデモを開く →(WebGPU 対応ブラウザが必要です。初回は WAD の読み込みに少し時間がかかります)
| 操作 | すること |
|---|---|
| ↑ ↓ | 前進・後退(移動速度 320 units/秒) |
| ← → | 左右に旋回(旋回速度 2.4 rad/秒) |
| , . / Alt+←→ | 左右に横歩き(ストレイフ) |
| Shift | ダッシュ(移動2倍) |
| Space | 使う(扉・スイッチ・リフト)。死亡時はリスポーン |
| Ctrl / マウス左 | 発砲 |
| 1〜7 | 武器切替(拳/ピストル/ショットガン/チェーンガン/ロケット/プラズマ/BFG) |
オリジナル同様、上下を向く操作はありません(DOOM の世界は高さ方向の照準を“自動”で合わせます)。カメラは地図の高さに沿って動く一人称視点です。
第3章
用語ミニ辞典
この先の章で出てくることばを先にまとめて紹介します。分からなくなったらここに戻ってきてください。
DOOM の全データ(地図・絵・音)を1つに束ねたファイル形式("Where's All the Data")。本体データを IWAD と呼びます。ここでは無料互換の Freedoom を使用。
WAD の中に並ぶ、名前付きのデータの塊1つ1つ。地図・テクスチャ・音などがすべてランプとして格納されています。
地図をあらかじめ木構造に切り分けておく手法。「この点はどの区画にいる?」を高速に答えられ、描画順にも使えます。
セクター=床と天井の高さを持つ“部屋”、リニデフ=壁の線、サイドデフ=線に貼るテクスチャ情報。DOOM の地図はこの3つでできています。
フラット=床天井用の 64×64 のタイル画像、パッチ=壁やスプライト用の“列”で圧縮された絵。どちらもパレット番号の並びです。
パレット=256色の対応表、COLORMAP=「この明るさなら何色に化けるか」の34段の変換表。DOOM の色と陰影の核心です。
ピクセルに RGB ではなく“色番号”を持たせ、表を引いて最終色を決める方式。当時のメモリ節約術で、あの独特の陰影の理由でもあります。
モンスター・弾・アイテム・置物——動くものすべての共通の器。位置・体力・状態などを持ちます。
DOOM のアクターは「インフォ(型)→ ステート(アニメの各コマ)→ アクション(AIの関数)」の表で動きます。データ駆動の代表例。
弾を飛ばさず、撃った瞬間に光線で当たり判定する方式。ピストルやショットガンはこれ。ロケットだけは弾(飛翔体)です。
2Dの絵を常にカメラへ正面を向ける板に貼って“立体っぽく”見せる技。DOOM の敵はすべてこの板です。8方向の絵を使い分けます。
Binary Angle Measurement。角度を32bit整数で表す DOOM 流の方法。ビット演算だけで「敵をどの方向から見ているか」を8分割できます。
DOOM のシミュレーション1コマ。1秒 = 35 tic固定。描画が速くても遅くても、ゲーム進行は常にこの刻みで進みます。
壁や床に割り当てられた“仕掛け”。扉・リフト・昇降床・スイッチ・出口などを、線と区画の番号で表します。
第4章
全体の地図
エントリの doom.ts(わずか49行)は、エンジンを立ち上げて WAD を取得し、あとは doom-level.ts にレベル作りを丸ごと任せます。
flowchart TD
ENTRY["doom.ts
エンジン・WAD取得(約28.8MB)"]
LEVEL["doom-level.ts
レベルの組み立て役"]
subgraph DATA["WADを解く"]
WAD["wad/*
バイナリ解析"]
end
subgraph VIEW["描く"]
GEO["geometry/*
壁と床の3D化"]
REND["render/*
素材・空・スプライト・武器"]
end
subgraph SIM["動かす"]
MOBJ["mobj/*
アクター(35Hz)"]
PLAY["player + combat + physics"]
SPEC["specials/*
扉・リフト"]
end
HUDSND["hud + sound"]
ENTRY --> LEVEL
LEVEL --> DATA
LEVEL --> VIEW
LEVEL --> SIM
LEVEL --> HUDSND
WAD --> GEO
WAD --> REND
矢印は「上が下を利用する」向きです。doom-level.ts(309行)が司令塔で、WAD を解いて→静的な壁と床を作り→動く仕掛け・敵・プレイヤーを用意し→毎フレームの更新ループを回します。「読む」「描く」「動かす」がフォルダごとにきれいに分かれているのが、このデモを読むときの最初の目印です。
更新ループの心臓は固定タイムステップです。1フレームの経過時間を最大 0.05 秒に抑え、1/35 秒たまるごとに「仕掛け→プレイヤー→世界」を1 tic 進める。だから PC が速くても遅くても、扉の開閉速度や敵の動きは常に同じ。オリジナル DOOM の 35Hz を厳密に守っています。
第5章
WADを読み解く
担当:wad/ フォルダ。生のバイト列を、意味のあるデータへ翻訳する“考古学”の層です。
まず wad-file.ts が入れ物を開けます。WAD は12バイトのヘッダ(識別子 IWAD/PWAD+ランプ数+目次の位置)に続いて、16バイトずつの目次(位置・サイズ・8文字の名前)が並ぶだけの素朴な構造。ここから名前でランプを引ける辞書を作ります。
flowchart LR
RAW["生バイト列"] --> WF["wad-file
ヘッダ+目次"]
WF --> MAP["map
頂点/線/区画"]
WF --> PAL["palette
256色+34段"]
WF --> GFX["graphics
パッチ/フラット/合成"]
MAP --> BQ["bsp-query
点→区画"]
map.ts は地図データを固定長レコードとして読みます。E1M1 という目印ランプの直後に、決まった順で並ぶ8種類のデータを、それぞれ正確なバイト数で切り出します。
| ランプ | 1件 | 中身 |
|---|---|---|
| VERTEXES | 4B | 頂点の座標 (x, y) |
| LINEDEFS | 14B | 壁の線(始点・終点・特殊番号・表裏の面) |
| SIDEDEFS | 30B | 面に貼る上・中・下テクスチャと所属セクター |
| SECTORS | 26B | 床/天井の高さ・テクスチャ・明るさ・タグ |
| SEGS / SSECTORS / NODES | 12/4/28B | BSPの線分・区画・分割ノード |
| THINGS | 10B | モンスター・アイテム等の配置(種類・角度) |
palette.ts は色の要。PLAYPAL(14種×256色×3バイト=10,752バイト)と COLORMAP(34段×256バイト=8,704バイト)を読み、両者を焼き合わせて 256×34 のルックアップ表テクスチャを作ります。これが次章の“本物の光”の材料です。graphics.ts は、列単位で透明を表現する DOOM 独特のパッチ形式や、64×64 のフラット、複数パッチを合成する TEXTURE1/2 を解読します。
最後に bsp-query.ts(43行)。「座標 (x, y) はどのセクターにいて、そこの床/天井の高さは?」を、BSP の木を根からたどって即答します。カメラ・モンスター・仕掛けが共通で使う、地図の“住所案内”です。
第6章
2Dの地図を3Dの壁に
担当:geometry/。DOOM の地図は本来“平面図”。それを立体の壁・床・天井に立ち上げます。
主役は build-level-geometry.ts(360行)。すべての壁の線(リニデフ)をたどり、その両脇のサイドデフから壁の四角形を起こします。座標は ワールド=(doomX, 高さ, doomY) で、DOOM の地図単位をそのまま1:1でワールド単位に使います(縮尺なし)。床と天井(フラット)は 64単位ごとにタイル貼り。
| 要素 | 作り方 |
|---|---|
| 一枚壁(片側のみ) | 中テクスチャを床→天井まで一枚張り |
| 段差(両側) | 床の高さが違えば下部、天井が違えば上部テクスチャを張る |
| 床・天井 | BSPで各区画の凸多角形を復元し扇状に三角形化 |
| 空の天井 | F_SKY1 の天井は張らず、背景の空を透かす |
床・天井の形は bsp.ts が復元します。地図全体を囲む大きな四角形を、BSP の分割線で次々に切り落としていくと、各区画のぴったりの多角形が残る——という賢い手法(Sutherland-Hodgman クリッピング)です。
オリジナル DOOM は、東西に伸びる壁を少し暗く、南北の壁を少し明るく描きます(±16)。実際の光源計算ではなく、平坦な迷宮に立体感を与えるための意図的なごまかし(fake contrast)。このデモも忠実に再現しています。各頂点の色に「そのセクターの明るさ」を仕込んで、次章のシェーダへ渡します。
そして扉やリフトのように動く床・天井は、静的な壁とは別に dynamic-geometry.ts が担当。仕掛けが「動いた」と知らせるたび、動く部分の面だけを作り直します(マテリアルは使い回し、GPUのメッシュだけ再生成)。
第7章
本物の光を再現する
担当:doom-material.ts。このデモが最もこだわった、「DOOM にしか見えない画面」の正体です。
ふつうの 3D は色を RGB で持ち、距離に応じて滑らかに暗くします。でも DOOM は違いました。テクスチャは「色番号」だけ(R チャンネルにパレット番号、A に不透明度)を持ち、明るさは COLORMAP という34段の変換表で「番号 → 別の番号」に置き換えて表現します。だから DOOM の陰影は、滑らかではなくカクッと帯状に落ちるのです。
// パレット番号を、明るさの段(row)ごとに引き直す // 明るいセクターほど浅い段。距離で段が深くなる。 baseRow = clamp(31 - floor(sectorLight / 8), 0, 31); lightRow = clamp(baseRow + depth / 224.0, 0, 31); // 224 = 1段ぶん暗くなるまでの距離(DOOM単位)
この DIST_PER_BAND = 224 が、あの「遠くが段階的に闇に沈む」距離感の数値です。シェーダは 256×34 のルックアップ表を、横=色番号・縦=明るさの段として引きます。色番号そのものは決して混ぜず(混ぜると存在しない色が生まれてしまう)、表を引いた後の最終 RGB だけを補間します。
近くの壁は 2×2 のバイリニアで軽く滑らかに、斜めに見た遠くの壁は最大16回のサンプリングを足し込んで、DOOM 名物の縦縞のチラつきを抑えます。「ドット感は残しつつ、目に痛いエイリアスは消す」——レトロ再現とモダンな品質の、絶妙な両立です。
第8章
空のからくり
担当:sky.ts(69行)。DOOM の空は「無限に遠い背景」。その錯覚を、たった1個の球で作ります。
仕掛けはこうです。カメラを中心に置いた直径 2000 の球を用意し、そのピクセルを強制的に最遠面へ(深度を反転Zの奥へ)押し込みます。すると空は必ず「すべての壁より後ろ」に描かれ、天井を張らなかった穴からだけ覗く。描画順を気にせず、空が確実に背景を埋めます。テクスチャは視線の方向から貼り、DOOM 流に360°で4回くり返します。空は距離や明るさで暗くならず、常に一番明るい段(row 0)で描かれます。
第9章
モンスターの設計図
担当:mobj/ フォルダ。DOOM の敵・弾・アイテムを支える、有名なデータ駆動アクターシステムの移植です。
あらゆる“動くもの”は mobj(マップオブジェクト)という共通の器。位置・体力・フラグ・状態を持ちます。その設計は3段構え——インフォ(型)→ ステート(アニメと行動のコマ)→ アクション(AIの関数)。この3つの表を think.ts が 35Hz で1 tic ずつ進めます。
flowchart LR
INFO["info
型(体力/速さ/半径)"] --> STATE["states
コマ{絵,フレーム,tics,行動,次}"]
STATE --> ACT["actions
AI関数(A_Look等)"]
ACT --> THINK["think
1ticずつ進める"]
THINK --> WORLD["world
全mobjの管理"]
info.ts の目録には、モンスター・アイテム・武器・弾・置物までがずらり。E1M1 に登場する主なモンスターはこちらです(数値はソース実測)。
| モンスター | 体力 | 速さ | 攻撃 |
|---|---|---|---|
| ゾンビマン(POSS) | 20 | 8 | ヒットスキャン(拳銃) |
| シャットガンガイ(SPOS) | 30 | 8 | ヒットスキャン(散弾) |
| インプ(TROO) | 60 | 8 | 近接+火球(弾) |
| デーモン/スペクター(SARG) | 150 | 10 | 近接のみ(噛みつき) |
| カコデーモン(HEAD) | 400 | 8 | 浮遊+火球 |
| バロン(BOSS) | 1000 | 8 | 火球 |
| ロストソウル(SKUL) | 100 | 8 | 浮遊・自発光 |
オリジナル DOOM は整数の固定小数点(FRACUNIT)で全計算していましたが、この移植はふつうの浮動小数点で、DOOM の地図単位をそのまま使います。読みやすさを優先した、現代的な割り切りです。
第10章
敵を動かす頭脳
担当:actions.ts。ステートの各コマに紐づく“行動”が、敵の思考そのものです。
DOOM の AI は驚くほどシンプルな関数の集まりです。ステートが進むたびに、そのコマに書かれた行動名が呼ばれます。
| 行動 | 中身 |
|---|---|
A_Look | プレイヤーが視界に入れば標的に設定し、覚醒(見え音を鳴らす) |
A_Chase | 標的へ接近。近ければ近接、条件が揃えば遠隔攻撃へ。8方向で移動 |
A_FaceTarget | 標的の方を向く |
A_*Attack | 各モンスター固有の攻撃(拳銃/散弾/火球/噛みつき) |
A_Pain / A_Scream / A_Fall | 被弾のうめき/断末魔/死んで当たり判定を消す |
攻撃するかどうかの判断(checkMissileRange)も DOOM 譲り。距離が近いほど発砲しやすく、遠いと撃ち控える確率計算になっています。近接の間合いは MELEE_RANGE = 64、遠隔の射程は MISSILE_RANGE = 2048(=32×64)。移動方向は「標的に近づく向き」を対角優先で選び、壁や仲間にぶつかれば別の向きを試します。
第11章
スプライトを板に描く
担当:sprites.ts と sprite-render.ts。DOOM の敵は3Dモデルではなく、1枚絵の板です。
モンスターは常にカメラへ正面を向くビルボード(板)に描かれます。でも、ただ正面を向くだけでは“書き割り”になってしまう。そこで DOOM は8方向ぶんの絵を用意し、「プレイヤーがどの角度から敵を見ているか」に応じて絵を差し替えます。横を向いた敵は横向きの絵、背を向けた敵は後ろ姿の絵、という具合です。
その角度計算が BAM(角度を32bit整数で表す方法)の見せ場。「視線→敵の方向」と「敵の向き」の差をビットシフトするだけで、8方向のどれかへ即座に振り分けられます。絵はスプライト名+フレーム文字+方向番号(例 TROOA1)で管理され、左右対称の向きは1枚を反転して使い回します。全スプライトは1枚の大きなアトラス(1024幅)に詰め込まれ、壁と同じ COLORMAP の陰影で距離に応じて暗くなります。
第12章
プレイヤーと武器
担当:player.ts と weapon-view.ts。体力・防具・弾薬・所持武器、そして手元の銃の描画です。
8種の武器はそれぞれ、弾の種類・連射間隔(tic)・発砲音を持ちます。開始時は拳とピストル、体力100、弾薬は弾丸50発から。
| 武器 | 弾 | 連射(tic) | ダメージ(1発) |
|---|---|---|---|
| 拳 / チェーンソー | — | 12 / 4 | 2〜20(近接64) |
| ピストル | 弾丸 | 12 | 5 / 10 / 15(散り±0.04) |
| ショットガン | シェル | 28 | 7発の散弾×5/10/15 |
| チェーンガン | 弾丸 | 4 | 5 / 10 / 15 |
| ロケット / プラズマ / BFG | ロケット/セル | 18 / 3 / 40 | 10〜50 |
手元の武器は weapon-view.ts が仮想 320×200 の画面に 2D で重ねます。移動中は上下左右に揺れ(横は cos、縦は sin の絶対値で“8の字”)、発砲した瞬間は発射コマ+別レイヤーのマズルフラッシュを 0.12 秒だけ重ねる。すべて COLORMAP の一番明るい段で、常にくっきり描かれます。
第13章
撃つ・当たる
担当:combat/attack.ts と physics/collision.ts。弾の当たり判定と、壁ずりの移動です。
ほとんどの武器はヒットスキャン——撃った瞬間に光線を飛ばし、最初にぶつかる壁までの距離を測り、その手前にいる敵を探して当てます。命中すれば血(BLOOD)、外れれば煙(PUFF)を出し、damageMobj が体力を削る。体力が尽きればモンスターは死亡ステートへ、被弾すれば painChance の確率でひるみステートへ遷移します。インプの火球だけは本物の飛翔体として飛び、着弾で爆発します。
移動と当たり判定は collision.ts。プレイヤーは半径16の円(高さ56、視点高41、登れる段差24)としてモデル化され、壁の線に沿って滑ります(法線方向に押し戻して接線方向の動きは残す=ウォールスライド)。両側が通れる壁は「すき間が身長より狭い/段差が24を超える」ときだけ塞がる。扉やリフトで高さが変わると、この判定もその場の高さで更新されるので、閉じる扉に挟まれます。
第14章
扉とリフト
担当:specials.ts(410行・最大のファイル)と special-types.ts。壁や床に仕込まれた“仕掛け”です。
DOOM の扉・スイッチ・リフトは、リニデフに割り当てられた番号で表されます。special-types.ts はその番号表(E1M1 が使う範囲)。「どう起動するか(押す/歩いて横切る/スイッチ)」「くり返せるか」「何をするか」を定義します。
| 番号 | 起動 | 動作 | 速度/待機 |
|---|---|---|---|
| 1 | 使う | 手動ドア(開いて待って閉じる) | 2 / 150 |
| 2 | 横切る | ドア開けっ放し | 2 / — |
| 117 | 使う | 高速ドア(ブレイズ) | 8 / 150 |
| 62 / 88 | スイッチ/横切る | リフト(下げて待って戻す) | 4 / 105 |
| 23 | スイッチ | 床を最低の隣接床まで下げる | 2 / — |
| 11 | スイッチ | レベル出口 | — |
specials.ts はこれを実際の“動く床・天井”に変えます。Space で使うと、正面へ 64 の光線を飛ばして手前のスイッチ/ドアを起動。歩いて線を横切れば、横断型の仕掛けが発火。ドアは「隣接する一番低い天井の4つ下」まで開き、150 tic 待って閉じます。
閉じかけのドアの真下にプレイヤーがいて、頭上の余裕が 56(身長)を切りそうなら、ドアは潰さずに再び開きます。オリジナルの“親切設計”まで再現。動いた区画は「汚れフラグ」を立て、第6章の動的ジオメトリが該当部分だけ作り直します。
第15章
ステータスバー
担当:hud.ts(342行)。画面下のあの茶色いバーを、WAD の本物のグラフィックから組み立てます。
体力・防具・弾薬・武器スロット・鍵——すべて WAD の STBAR 系グラフィックを1枚のアトラスに焼き、仮想 320×200 の座標(バーの上端 y=168)に、当時のレイアウト定数どおりに並べます。数字も本物のフォント絵です。
中央の DOOMガイの顔も再現。体力から痛みレベル(0〜4)を出し、被弾直後は「イテッ」という顔、死ねば骸骨、平常時は 0.5 秒ごとに左・正面・右へ視線を動かします。DOOM に無かった十字カーソルだけは、遊びやすさのために作者が足したもの(DOM オーバーレイ)です。
第16章
音
担当:sound.ts(86行)。効果音は合成ではなく、WAD の中の本物のサウンドを鳴らします。
DOOM の効果音は DS で始まるランプ(例:DSPISTOL)に、DMX 形式の 8bit PCM として入っています。sound.ts はこれを解読し(サンプルレートは通常 11025Hz、前後16サンプルの余白は切り落とす)、Web Audio の AudioBuffer に変換して再生。同じ音の連発は 1 tic(1/35秒)に1回まで、音量は 0.6 に抑えます。ブラウザの制約で、音は最初のキー操作の後から鳴り始めます。
第17章
設計テーマ
29ファイルに散らばって見えて、じつは一貫した4つの考え方が通っています。
GPLのDOOMソースは見ない・写さない。公開仕様だけを頼りにゼロから実装し、データも自由な Freedoom を使う。だから堂々と公開・教材化できる。
モンスターも仕掛けも、ロジックではなく表で定義。インフォ→ステート→アクション、線番号→動作。表を足すだけで敵や仕掛けが増える。
1:1のスケール、±16のfake contrast、224単位ごとの帯状の闇、パレット番号を混ぜない描画。細部の再現が「DOOMにしか見えない画面」を作る。
見た目は可変フレーム、ゲームは35Hz固定tic。この分離が、PCの速さに左右されない“当時のままの手ざわり”を保証する。
このコードのコメントには「なぜそうしたか」と「どの公開資料に基づくか」がていねいに書かれています。GPLソース不参照の宣言/閉じるドアが潰さず反転する理由/巨大な床を影から外す判断——判断の理由ごと読めるのが、このサンプルの教材価値です。Minecraft・Platformer・Tetris・Sandblox デモと共通する“コメント文化”が、ここにも息づいています。
第18章
ファイル一覧(全29ファイル)
コードリーディングのおともに。行数は master ブランチのソース実測値です。specials.ts が最大で、合計およそ5,010行。
| ファイル | 行数 | やくわり |
|---|---|---|
| エントリ・司令塔 | ||
doom.ts | 49 | エンジン起動・WAD取得・レベル構築の呼び出し・ループ開始 |
doom-level.ts | 309 | レベル全体を組み立て、35Hz固定ticの更新ループとカメラを回す |
| WAD解析 | ||
wad/map.ts | 219 | 地図ランプ(頂点/線/面/区画/BSP/配置)を固定長で解析 |
wad/graphics.ts | 192 | パッチ/フラット/PNAMES/合成テクスチャの解読 |
wad/wad-file.ts | 100 | WADの入れ物(ヘッダ+目次)を開き、ランプを引く |
wad/palette.ts | 75 | PLAYPAL/COLORMAPを256×34のルックアップ表テクスチャに |
wad/bsp-query.ts | 43 | 点→区画・床/天井高さをBSPで即答(住所案内) |
| ジオメトリ | ||
geometry/build-level-geometry.ts | 360 | 2D地図→3Dの壁/床/天井をテクスチャ別に生成(fake contrast) |
geometry/bsp.ts | 107 | BSP分割面で各区画の凸多角形(床天井の形)を復元 |
geometry/dynamic-geometry.ts | 84 | 扉・リフト等の動く面だけを再生成 |
| レンダリング | ||
render/sprites.ts | 291 | スプライトを解読しアトラス化、8方向から正しい絵を選ぶ |
render/weapon-view.ts | 224 | 一人称の武器を2Dで重ね、揺れとマズルフラッシュ |
render/doom-material.ts | 159 | パレット+COLORMAPの帯状陰影を再現するWGSLマテリアル |
render/sprite-render.ts | 107 | 全mobjをカメラ正面のビルボードとして描画 |
render/sky.ts | 69 | F_SKY1の空。反転Zの最遠面に押し込む球 |
render/texture-cache.ts | 69 | 壁/床テクスチャを必要時にGPUテクスチャへ変換・キャッシュ |
| アクター(mobj) | ||
mobj/info.ts | 219 | 全アクターの型目録(体力/速さ/半径/フラグ/音) |
mobj/actions.ts | 201 | AI・攻撃の行動関数(A_Look/A_Chase/各攻撃) |
mobj/world.ts | 199 | THINGSからmobjを生成、毎tic進行・取得・ビルボード列を作る |
mobj/states.ts | 177 | ステート表(絵/フレーム/tics/行動/次)と各mobjの入口 |
mobj/think.ts | 126 | 1ticの進行・移動・重力・モンスターの歩行 |
mobj/mobj.ts | 67 | Mobj構造体と8方向の向き定義 |
| プレイヤー・戦闘・物理 | ||
player/player.ts | 269 | 体力/防具/弾薬/武器の状態と、選択・発砲・被弾・取得 |
combat/attack.ts | 211 | 視線判定・ヒットスキャン・飛翔体・ダメージと状態遷移 |
physics/collision.ts | 181 | 円vs線の移動・壁ずり・段差・mobj同士の押し合い |
| 仕掛け・UI・音 | ||
specials/specials.ts | 410 | ドア/リフト/床/スイッチ/出口の実行時ロジック |
hud/hud.ts | 342 | 本物のSTBARグラフィックでステータスバー+表情の顔 |
sound/sound.ts | 86 | WADのDMX音(DS*)をWeb Audioで再生 |
specials/special-types.ts | 65 | リニデフ特殊番号の表(速度/待機/起動方法) |
行数は master ブランチ(2026年時点)のソース実測値です。合計およそ5,010行(29ファイル)。