Three.jsを諦めた日があった。でもその判断が、結果的にゲームの動きをよくした。魔球BATTERのボールは、Three.jsなどの3Dライブラリに頼らず、CSSとJavaScriptの数式だけで立体的な動きを実現しています。この記事では、ボールの座標計算・遠近感・影の動きを担うエンジンの設計思想をご紹介します。

Three.jsなしで「本物らしい動き」を実現したかった

開発初期、私はThree.jsを使った3Dレンダリングを試みていました。しかし、パフォーマンスとメンテナンスコストの問題から、最終的に「CSSと数学で全部やる」という方向に転換しました。「本当にできるのか?」という不安はありました。でも、やってみると思った以上にリッチな動きが実現できた——その経験が、このエンジンに対する私の自信の源です。

progress基準の座標計算

ボールの位置はすべて「progress(0.0〜1.0)」という一つの変数で制御されます。0.0がピッチャーの手元、1.0がストライクゾーン到達です。各フレームでprogressが増加し、それに応じてX座標・Y座標が決まります。curve_xとcurve_yというパラメータで球の曲がり方が決まり、sin関数を使って滑らかなアーク軌道を描きます。この「progress一元管理」のシンプルさが、デバッグやチューニングを直感的にしています。

各魔球の特殊処理

通常の軌道計算に加え、各魔球タグに応じた特殊処理が加わります。STOP_AND_GOは40〜60%の区間でprogressの進みを10分の1に減速させ、「止まる」感覚を作ります。LOOP(ループ魔球)は30〜70%の区間でcos/sin関数による円運動を加算し、ボールが宙でくるりと回る軌道を生みます。UNDERGROUND_EMERGEはY座標に+60の大きなオフセットをかけてボールを画面外(地面下)に潜り込ませ、出現タイミングでオフセットをゼロに戻します。SKY_DROPはY座標に-90のオフセットを入れ、高い空から降ってくる感覚を演出します。

影と遠近感で「立体感」を作る

ボールの見た目を立体的にする工夫が2つあります。一つ目はスケール変化です。ボールはピッチャー側では小さく(スケール0.4)、バッター手前では大きく(スケール1.7)なります。この遠近変化だけで、画面が2Dでも「ボールが近づいてくる」感覚が生まれます。二つ目は影です。ボールの「地面からの高さ」をリアルタイムで計算し、高いほど影が薄く・小さく、低いほど影が濃く・大きくなります。この影の変化がボールの高さを直感的に伝え、タイミング判断の手がかりになります。

「純粋な数学」への敬意

Three.jsを使えばもっと簡単に3Dが実現できます。電波や実行環境に左右されず、かつ驚くほど軽量に動く3Dゲームの裏側には、こうした数式による手作りの物理エンジンがあります。ぜひ、こちらの紹介ページから魔球BATTERの立体的な物理表現を実際にプレイして体感してみてください。