【プチコン/mkII 両対応】
前回は疑似3Dゲームとしてスキーゲームを作ってみましたが今回は疑似3Dのレースゲームを作ってみることにします。
CLS A$="■■■■■■■■■■■■■■■■■■■■" '■を20個 R=0 B=0 C=0 FOR I=0 TO 9 D$=MID$ (A$,0,20-I*2) LOCATE 6+I+A,23-I PRINT C$; C=C+R/12 B=B+C NEXT @LOOP GOTO @LOOP |
VISIBLE 1,,,,,1 GPAGE 0 GCLS R=4 A=0 B=0 FOR I=1 TO 70 W=150-I*2 GLINE 128+A-W/2,192-I,128+W/2+A,192-I,15 B=B+R/80 A=A+B NEXT |
VISIBLE 1,,,,,1 GPAGE 0 GCLS R=4 A=0 B=6 W=150 Y=191 FOR I=0 TO 49 GFILL 128+A-W/2,Y,128+A+W/2,Y,15 A=A+R/1.5 B=B*0.94 W=W*0.94 NEXT |
コラム レースゲームにおける道路の3D表現3D(疑似3Dも含む)のレースゲームを作る場合には道路をいかに表現するかが最初の難関になります。これがまっすぐ1本の直線の道路ならばあらかじめ道路両脇を直線で結んでおけばそれで済む問題(ただし、これでも前回の講座のように拡大率の変え方は考慮しなくてはならない)ですが、カーブを表現する場合にはそうもいきません。この講座ではこの難しいカーブの表現をいかにして簡単に行うかを重視したものになっていてその中で違和感が少なく簡単な式で表すことができるものを選択しました。しかし、この方法は疑似3Dなら問題ないのですが、「正確な3D表示」とは言えないのです。 正しく表現するための方法としてはポリゴンやワイヤーフレームといった3DCGで道路を表現するというものがあります。これはプチコン用ポリゴン表示プログラムを見ての通り非常に重い処理となっていてプチコンで行うにはかなり無理があるでしょう。頂点数を減らしたかなり簡略化されたコースをワイヤーフレームによって表現すれば何とか実用に耐えうる速度(15fps程度)を実現可能ですが厳しいのは確かです。 ポリゴンやワイヤーフレームがなぜ重いかというとどの角度から見ても(計算的上)正しい表現ができるようにするための回転処理(ジオメトリ処理)が重いのが1つの理由です。それに加えてポリゴンでは面の塗りつぶし処理も自前で用意しなくてはならず、それが重くしている理由にもなっています。ワイヤーフレームはポリゴンと比べると描画処理は桁違いに軽くなるのですが、手前の面で隠れている線を非表示にする処理(カリング)を加えると法線ベクトルの演算が必要になってくるため非常に重くなります。 では、上記の図2の(A)のように道路は細長い長方形によって構成されていると考えたらどうでしょうか。これを斜め後ろから見下ろすだけならばを正しく表示するのは簡単そうに思えるかもしれません。 実はカメラの向きが道路(地面)に対して平行なら下記のようなごく簡単な一次式で表すことが可能なのです。 SX=128+X/Z*10 SY=96-Y/Z*10 この式の具体的な意味はこちらに書いているのですが、簡単に説明すると変数Zがカメラとの距離であり距離に比例して小さく見えるというパースの大原則を数式化しただけのものです。スプライトを使った疑似3Dゲームを作る場合にはSPHOMEで設定したスプライトの中心座標をこの式によって求めることができます(SPSCALEの値はZの値に反比例する)。また、立体の各頂点に適用してこの式によって得られた座標を線で結べばワイヤーフレームも可能です。レースゲームに使用する場合には後方視点の場合は自車のZ座標を0に設定した方が判定がしやすいですが、その場合にカメラと自車の距離が20ならばX/ZをX/(Z+20)とすれば良いです。 ただし、カメラが地面に対して平行というのは一点透視の状態であり、消失点(直線道路を表示して道路両脇の線を延長した線が交差する座標)がアイレベル(カメラのある視点の高さ)になります。言うまでもなく車は空中ではなく道路の上を走っているのですが、透視図の性質上消失点から離れれば離れるほど誤差が出てくるためこのようにカメラを地面と平行にした状態ではアイレベルが高くなればなるほど大きな誤差が出てきます。(誤差を少なくするためにはカメラのレンズを標準〜望遠にする必要があるけど道路の遠くを良く見せるためにアイレベルを高くしてなおかつ自車を画面内に入れようとするとどうしても広角気味になってしまう) 消失点からの視角のずれによる表示誤差を減らすには自車を消失点(この場合の正しい表現でいえば「視心」となり、一般的な3DCGや透視図だとこの視心に近いほど正確に表現できる)の上に置けばいいです。簡単に言えば、自車に向けて見下ろすようにカメラの向ける角度を変えてしまえばいいだけです。そのようにして、出来たのがこの「2D→3D レース」(プレイ動画はこちら)です。このゲームは道路が長方形で構成されていてその長方形を見下ろした場合もGFILLで簡単に描画できるように長方形にしているという点を除いては非常に正確な計算を高速に行っています。 これは簡単に言えば「縦回転」となっていてX軸回転レースゲームと言えます。ちゃんと正確に計算を行っているため0度〜90度までどのようなカメラアングルであっても正しく表示することが可能になっています。(一見正確な表示ができそうなポリゴンやワイヤーフレームであっても上記の視心からのずれによる誤差などが原因でカメラの位置やレンズの設定によっては表示に不自然さが出てしまうため決して万能なものではないことに注意して欲しい) ただし、このゲームをプレイするかプレイ動画を見たら分かるように単純な縦スクロールのレースゲームを3Dで表示しているだけなのです。それはこのゲームはジグザグコースを表現することはできるのですが、カーブを表現することはできないためです。 このゲームでカーブを表現するためにはX軸回転だけではなくZ軸回転(真上から見た場合に普通に時計回りや反時計回りに回転しているように見えるもの)を加えた2軸回転が必要になってきます。2軸回転はスーファミの「F-ZERO」や「マリオカート」などではごく普通に使われていますが、これはスーファミがBG画面の2軸回転をハードウェアでサポートしており非常に高速に行えるためです。プチコンではそういう機能がないためプログラムで実現する必要があります。 プチコンで2軸回転を行うプログラムはこちらに用意しました。これを使って簡単なレースゲームを作ってみましたがこのサンプル動画のようにプチコンで実用レベルの速度(15fps程度)を得るためにはどうしても解像度が低くなってしまいそれが原因でスピード感も感じさせなくなってしまいます。 もしも、プチコンで2軸回転を使ったレースゲームを作るならば回転はZ軸回転のみにしてカメラの向きは地面に水平に固定としてX軸をリアルタイムで回転させるのをやめないと厳しいでしょう。カメラアングルを変える表現をしたいとか画角が極端に広角にならない限りはこれで問題はないと思います。(カメラの向きが地面に水平で固定ならば速度面で有利になるためそれで2軸回転風のレースゲームを上手く作っている人もいる) つまり、正確に計算を行えば行うほど誤魔化しが効かなくなるためにカーブの表現が難しくなるということです。レースゲームにおいてカーブの存在は見た目の変化だけではなくカーブの曲率によって速度を調整するという戦略的要素も含んでいるため非常に重要だと思われます。(タイムアタック重視のゲームだと速度調整の戦略性がないとゲームとして全く楽しめなくなる) したがって、今回の講座のように「カーブの表示をいかに簡単に行うか」というところから出発して違和感が少しでも無くなるような簡単な方法(1画面に収まるようなレベル)で作るというのも正しいアプローチの1つだと思います。そして、正確さよりもそれっぽさを重視できるのが疑似3Dのメリットだと思います。 |
《 このゲームにおいてZ字カーブが不自然な理由 》Z字カーブは直線で構成されたカーブとなっています。つまり、常に曲線で構成されているS字カーブとは異なり、コースデータのつなぎ目部分以外は直線と同じ扱いになるわけです。その結果下記の2つの問題が出てきます。(1) プレイヤーの視点 (2) 遠心力 (1)のプレイヤーの視点についてですが、このPETIT RUNでは常に道路において平行となっています。カーブにおいては接線の方向に視点があるということです。これは言い換えると進行方向に視点があるともいえます。そうすることで回転処理をしなくても済むため処理が単純化でき高速化かつリスト短縮が可能になっています。 これがカーブが曲線ではなく直線となるZ字の場合だと例えば曲率ー2→曲率-2のように同じ曲率(同じコースデータ)が続いているという時には単なる直線(画面中央を消失点とした道路)として表示されることになってしまいます。また、そのように表示をしたら曲率ー2→曲率ー1にコースが変わる場合には本来ならば曲率ー1は左カーブですが表示上は右カーブになってしまうのです。(曲率ー2が直線扱いであるため) したがって、現状の「常に道路に平行な視点」では不自然さが出てしまい、視点は道路と無関係に常に特定方向に統一することになります。これは昔ながらの縦スクロールのレースゲームと同じと考えれば分かりやすいでしょう。 (2)の遠心力は後述のように自キャラの挙動において大きな役割を担っています。速度を上げれば上げるほどカーブが曲がりにくくなるため遠心力があることで減速を活用する必要性が出てくるからです。 Z字カーブは自キャラの挙動は直線と同じになるため遠心力は働きません。したがって、遠心力のパラメータは導入できません。 実際はカーブかどうかではなくハンドルを切った時点で円運動となるために遠心力が働くので直線だけで構成されているから遠心力のパラメータが導入できないということはないのですが、仮にZ字カーブでハンドルを切ったときに遠心力が働くようにした場合には視点と進行方向が異なっているためこのPETIT RUNの表示アルゴリズムで自キャラを円運動させるような挙動を行えば不自然さが単に拡大されるだけとなってしまいます。 その点、このゲームでは常に進行方向(視点)は接線方向となっており、カーブの際は基本的にカーブにそってハンドルを切るため遠心力が自然に表現されています。(つまり、急カーブになるほど急ハンドルを切っているのだけどこれが処理の単純化にも繋がっている) つまり、このゲームにおいてS字ではなくZ字カーブを導入すると表示や自キャラの挙動が不自然になってしまうというわけです。したがって、根本的な面からゲームシステムを変える必要性が出てきます。もしも、Z字カーブを導入したらどうなるかは上記コラムで紹介した「2D→3D レース」をプレイしてみたら分かると思います。(このゲームは縦スクロールゲームだけどリアルタイムで縦方向に画面回転させることで疑似3D表示をしているだけなので) |
11行目 E=7 を E=3 に変更 14行目 FORの前に D=0 を追加 14行目 V=V+R+R を D=D+R/5:V=V+D に変更 18行目 E=E*P:F=F*P を F=F-4.5 に変更 |