■Unity開発メモ用のWiki◎現在扱っていること・Unity全般・MMDからUnityへの変換してインポート・MMDの仕様把握・BlenderでMMDモデルのカスタム





参考サイト

数学はどのくらい必要ですか?

もしあなたが
三角測量の知識があれば、このチュートリアルで必要な数学はこれだけです。
代数と幾何の知識があれば、FOVの説明は不要です。
できるだけ数学を避けたい人は、次の本を読んでください。最も単純な道、カーブとステアリング、スプライトとデータ、そして丘陵地帯
これは非常に柔軟なテクニックで、実は足し算だけでもなんとかなるのです もっと高度な計算をすれば見栄えも良くなりますが、「ポールポジション」や初代「アウトラン」のようなゲームに見られるレベルまでなら、計算だけで済ませることも可能です。

プログラミングの知識はどれくらい必要?

ラスターグラフィックスを理解することは、とても役に立ちます。スキャンラインとは何か、各ラインはピクセルの列で構成されていることを知っていること。プログラミングの例は疑似コードで書かれているので、特定の言語の経験がなくても理解することができます。

準備はいいですか?さっそく始めましょう

ラスター効果 - 背景

擬似3D道路は、ラスター効果と呼ばれるより一般的な効果のバリエーションに過ぎません。ラスター効果の最も有名な例の1つは、「ストリートファイターII」です。ファイターが左右に動くと、地面が遠近法でスクロールします。これは、実は3Dではありません。地面のグラフィックは、極めて広角なパースペクティブショットとして保存されているのです。スクロールするとき、遠くにあるはずの画面の線は、近くにある線よりもゆっくりとスクロールします。つまり、画面の各ラインが独立してスクロールするのです。下図は、最終的な画像と、メモリに保存されている地上絵の両方です。

道路の基礎知識

ラスターロードの紹介
私たちは、3次元空間上に頂点が浮遊するポリゴンを使って3次元効果を考えることに慣れている。しかし、昔のシステムは、3次元の計算を大量に行うほどの性能はなかった。一般的に古いエフェクトは、ラスターエフェクトというカテゴリーに分類されるものが多い。これは、1行ごとに何らかの変数を変化させることで行う特殊効果です。最も一般的なのは1行ごとに色やパレットを変えたり、1行ごとにスクロールさせたりすることです。これは、スクロールのためのアクセラレーションを持ち、インデックスカラーモードを使用していた古いグラフィックハードウェアに適しています。

疑似ラスタロード効果は、静止画像を歪めて3Dの錯覚を作り出すという点で、実はストリートファイターIIのパースペクティブ効果と似たような働きをします。その方法は次のとおりです。

ほとんどのラスターロードは、まず平坦な道路の画像から始まります。これは基本的に、地面上にある2本の平行線が遠くへ向かって後退していくグラフィックです。遠景になるにつれて、2本の線は接近しているように見えます。これは、遠近法の基本的なルールです。さて、アーケードのレースゲームでは、動いているように見せるために、道路に縞模様が描かれていることがほとんどです。この道路上のストライプを前方に移動させるには、一般にカラーサイクリングで行うか、ラインごとにパレットを変更することで行います。カーブとステアリングは、ストリートファイターIIのように、各ラインを独立してスクロールさせることで実現されます。

カーブとステアリングについては、次章で説明します。とりあえず、それは置いておいて、道路が前方にスクロールしているように見えることに集中しましょう。

最もシンプルな道

上のような道路をイメージしてみよう。道路の左端と右端を示す2本の平行線は、遠方へ後退していく。このとき、2本の平行線は遠くへ離れていくが、見る人には2本が接近しているように見える。下はその様子。

この絵に欠けているのは、距離感をよくするための道路標識である。ゲームではこのような効果を得るために、明暗を交互に繰り返す路面標示を用いますそのために、「テクスチャ位置」という変数を定義しておきましょう。この変数は、画面の一番下を0として始まり、画面の上に行くに従って増えていきます。この値が一定以下のときは、道路は1つの色合いで描かれる。この値が一定以上のときは、もう一方の陰影で描かれる。そして、位置の変数は、最大値を超えるとゼロに折り返され、パターンが繰り返される。

というのも、そうすると道路が遠ざかるにつれて小さくなっていくわけではなく、複数の異なる色の帯が見えるだけになってしまうからである。つまり、一定量だけ変化する別の変数が必要で、それを行ごとに別の変数に追加し、最後のものをテクスチャの位置の変化に追加するのです。

以下は、画面の下から、各行が遠くに後退するにつれて、Z値がどうなるかを示す例です。変数の後に、次の行の値を得るために追加されるものを表示しています。DDZ(デルタZ)、DZ(デルタZ)、Zと名付けましたが、DDZは一定、DZは直線的に変化し、Zは曲線的に値が変化します。ZはZ位置を表し、DZは位置の速度を保持し、DDZは位置の加速度(加速度の変化)であると考えることができる。なお、私が選んだ4という値は任意であり、この例には都合が良かっただけである。
DDZ = 4 DZ = 0 Z = 0 : dz += 4, z += 4
DDZ = 4 DZ = 4 Z = 4 : dz += 4, z += 8
DDZ = 4 DZ = 8 Z = 12 : dz += 4, z += 12
DDZ = 4 DZ = 12 Z = 24 : dz += 4, z += 16
DDZ = 4 DZ = 16 Z = 40 : etc...

DZが先に変更され、それがZの変更に使用されることに注目。要約すると、速度4でテクスチャを移動しているとします。 つまり、1行目の後、位置4のテクスチャを読み込んでいることになります。次のラインは12になります。その次は24。このように、どんどんテクスチャを読み込んでいくわけです。このように私はこれらの変数を、テクスチャポジション(テクスチャのどこを読んでいるか)、テクスチャスピード(テクスチャを読み切る速さ)、テクスチャアクセラレーション(テクスチャスピードを上げる速さ)と呼びたいのです

同じような方法で、カーブや坂道も描けるので、あまり数値計算をする必要はありません。さて、道路が動いて見えるようにするには、フレームごとにテクスチャの位置が画面下部のどこから始まるかを変えればよい。

さて、このトリックには欠点があることにお気づきでしょうか。ズームのレートが不正確なのです。このため、「オートミール効果」と呼ばれる歪みが発生します。これは、初期の疑似ゲーム「OutRun」などで見られた、画面の中心から外側に向かうにつれて、道路の縞模様などのオブジェクトの速度が遅く見えるゆがみ効果である。

この方法にはもう一つ欠点があり、特に坂道がある場合、遠距離のZ値を予測することが難しいのです。ここでは、より高度な方法として、Zマップと呼ぶ方法を学びます。これは、画面の走査線ごとにZ距離がどうなっているかを計算する表です。しかし、その前に、もう少し計算が必要です...。

数学の遠回り 3D遠近法投影

オートミール効果を取り除く方法があります。しかし、それらを可能にするためには、いくつかの伝統的な3次元数学が必要です。必要なのは、3次元の座標を2次元の表面にフィットするように変換する方法です。

上の図では、眼球(左下)がスクリーン(青い縦線)を通して3次元世界の物体(「y_world」)を見ています。眼球はスクリーンから距離「dist」、物体から距離「z_world」です。さて、幾何学や三角法を学んだことのある人ならお気づきかもしれませんが、この絵には1つではなく、2つの三角形があります。最初の三角形は一番大きなもので、眼球から右側の地面、そして私たちが見ている物体までが描かれています。2つ目の三角形は、私が黄色に着色したものです。これは、眼球から、画面上で私たちが見ている物体まで、そして地面まで下りて、戻ってきたところです。

この2つの三角形の斜辺(眼球から物体までの線)は、一方が他方より長くても同じ角度になります。つまり、同じ三角形でありながら、小さい方の三角形が縮小されているのです。このことは、横と縦の辺の比が同じでなければならないことを意味しています。数学の用語で言うと
y_screen/dist = y_world/z_world
→(三角比と相似)
ここで必要なのは、y_screenを得るために方程式をこねくり回すことです。これによって得られるのは
y_screen = (y_world*dist)/z_world
→両辺を「dist」で割る

要するに、画面上のオブジェクトのy座標を求めるには、yワールド座標を取り、それに画面までの距離を掛けて、ワールド内の距離で割ればいいのですもちろん、これだけでは画面の左上隅が視野の中心になってしまいます。y_world=0と入力するだけで、このようになります。これを中央に配置するには、画面解像度の半分を結果に追加して、ちょうど真ん中に配置すればよいのです。また、鼻をスクリーンに近づけることで、方程式を少し簡略化することができます。この場合、dist=1です。そうすると、最終的な方程式は次のようになります。
y_screen = (y_world/z_world) + (y_resolution/2)
比率と視野角の関係や、解像度に依存しない画像のスケーリングもありますが、道路の問題を解決するためには、そのようなことは必要ないでしょう。画面の端に対する角度が視野角となり、同じ関係が成立するのです。

もっと数学的に 3Dプロジェクションに視野を追加する

さて、これはほとんどのロードエンジンのケースではほとんど不要です。しかし、投影パラメータを解像度に依存しないようにしたり、回転が必要なオブジェクトや、真の3D効果との統合には有効です。

元の投影式に戻りましょう。"上の説明で出てきた [dist]を[scaling ]と呼ぶことにします"。
y_screen = (y_world*scaling)/z_world + (y_resolution/2)
このアイデアは、画面上のすべてのポイントをある値でスケーリングする必要があり、それによって特定の視野(FOV)内のポイントを表示したままにすることができます。FOVx の定数とFOVy の定数が必要です。

例として、640x480の解像度で作業し、60度のFOVが必要だとします。横から見た3D投影の図を見てきました。ここでは、代わりにこの投影空間の上面図を見てみましょう。

この問題を考える1つの方法は、オブジェクトがFOVの右端にある場合、x=640で画面に表示される必要があるということです(640x480なので)。図を見てみると、FOVは2つの直角三角形に分けることができ、それぞれの角度はfov_angle/2(a/2)です。そして、FOVは円錐形なので、オブジェクトは、x=R*sin(a/2) and z=R*cos(a/2), Rは任意の半径値で、FOVの右端に位置しています。R は任意の半径値です。R=1 にすることもできます。そして、オブジェクトはx_screen=640に表示される必要があります。そうすると、次のようになります (基本的な投影式から始めます)。

x_screen=640 fov_angle=60 y_world=sin(60/2) z_world=(60/2) x_resolution/2=320 scaling=?

x_screen = (y_world*scaling)/z_world + (x_resolution/2)
640 = (sin(30)*scaling/cos(30)) + 320
320 = tan(30)*scaling
320/tan(30) = scaling

一般的な用語で: scaling = (x_resolution/2) / tan(fov_angle/2)
a/2 を 30 (60度の半分) に置き換え、sin/cos = tan と認識し、出来上がりです。視野の右端に物体を置いて、この値を元の投影式に代入し、Xの値が640になることを確認すれば、これをテストできるはずです。例えば、(20, 34.64) の (x, z) 点は、20 は 40*sin(30) であり、34.64 は 40*cos(30) なので、X=640 になります。

水平方向の標準モニターとワイドスクリーンモニターでは、水平(x)と垂直(y)に異なるFOV値があることに注意してください。

より正確な道 - Zマップの使用

パースペクティブの問題を解決するためにやりたいことは、画面の各ラインの距離のリストをあらかじめ計算することです。つまり、3次元の平面をどう表現するかが問題なのです。この仕組みを理解するために、まず2次元に相当するものを考えてみましょう。2次元で水平な線を表現するには、どの座標(x, y)でもyは同じであると言うでしょう。これを3次元に拡張すると、平面となり、xとzの距離に対して、yが同じになります 水平な平面の場合、カメラからの距離に関係なく、yは常に同じです。同様に、点がどれだけ左右にずれていても、yは同じになります。話を戻して、画面の各ラインの距離を割り出すことですが、これをZマップと呼ぶことにします。Z Mapの計算は、3dプロジェクションの式を並べ替えて、各スクリーンYのZ値を求めるだけです!

まず、前節の式で
Y_screen = (Y_world / Z) + (y_resolution / 2)

さて、Y_screen(各行)が与えられているので、Zを求めるように方程式をこねます。
Z = Y_world / (Y_screen - (height_screen / 2))

Y_world は基本的に地面とカメラの高さの差で、マイナスになる予定です。これは各行で同じです。なぜなら、冒頭で説明したように、当面は平らな道路に興味があるからです。この方法は、見た目がより正確で、「オートミール効果」を避けることができるほか、最大描画距離を簡単に計算できる利点があります。

道路はこのバッファを読み込んで画面にマッピングされる。それぞれの距離について、道路テクスチャのどの部分がそこに属するかを、テクスチャの各ストライプまたはピクセルが何単位を占めるかを記録することによって、把握しなければなりません。

スクリーンの各行の距離はわかりましたが、道路の幅や各行のスケールファクターをキャッシュしておくと便利な場合があります。スケールファクターは距離の逆数で、プレイヤーのカーグラフィックが最も長く滞在する行で値が1になるように調整されます。これは、指定されたライン上にあるスプライトのスケールや、道路の幅を求めるために使用することができます。

カーブとステアリング

カーブさせる

道路をカーブさせるには、カーブ形状の中心線の位置を変えればいいのです。これにはいくつかの方法があります。一つは、「最も単純な道路」で行ったZの位置の変更と同じように、3つの変数で行う方法です。つまり、画面下部から、1ラインごとに道路の中心が左右に移動する量を着実に増やしていくのです。テクスチャの読み込みと同じように、この変数を「中心線(カーブ)位置」「カーブ速度」「カーブ加速度」と呼ぶことができます

しかし、この方法にはいくつか問題があります。ひとつは、S字カーブはあまり使い勝手がよくないということ。もうひとつは、カーブを曲がるときと曲がったときが同じに見えること。道路は曲がり、そして単に曲がらない。
この状況を改善するために、ロードセグメントという考え方を導入する。ロードセグメントとは、プレイヤーからは見えない仕切りのことです。目に見えない水平方向の仕切りで、その線の上に道路のカーブが設定されていると考えてください。あるとき、このセグメントの仕切りの1つが画面の底にあり、もう1つが画面の底に向かって一定の速度で下降しています。一番下にある区間は、道路の最初のカーブを決めるので、ベース区間と呼ぶことにする。その仕組みはこうです。

道路を描き始めると、まず基点を見て、それに応じて描画のパラメータを設定する。曲がり角が近づくと、セグメントラインは他の道路オブジェクトと同じように、遠くから始まってプレイヤーに向かってきますが、スクリーンの下を一定の速度で流れていく必要があります。つまり、プレイヤーの移動速度に合わせて、セグメントデバイダーは1フレームあたり何本の線で画面を下降していきます。あるいは、Zマップを使用している場合は、1フレームあたり非常に多くのZマップ・エントリーがあります。もし、線路上の3Dオブジェクトがそうであるように、セグメントもプレイヤーに向かって「加速」すると、道路は大きく揺れ動くことになります。

これがどのように機能するか見てみましょう。左カーブのセグメントラインは、道路の半分にあり、ベースセグメントはまっすぐな道路だとします。道路が描かれると、「左カーブ」のセグメントにぶつかるまで、カーブが始まりません。そして、道路のカーブは、そのポイントによって指定された割合で変化し始める。移動するセグメントがスクリーンの底に当たると、それは新しいベースセグメントになり、それまでベースセグメントだったものは、道路の上に行くようになります。

下図は2つの道路です。1 つは、直線の後に左折するもので、もう 1 つは左折の後に直線があるものです。どちらの場合も、セグメントの位置はZ Mapの半分(または画面の半分)です。つまり、道路は途中でカーブや直線になり始め、カメラは1枚目の写真ではカーブに入り、2枚目の写真ではカーブから離れることになります。

そして、これは同じ手法で、同じセグメント位置をS字カーブに適用したものです。

セグメントの位置を記録する最も良い方法は、Z マップのどこにあるかという点です。つまり、セグメントの位置を画面のY位置に結びつけるのではなく、Zマップの位置に結びつけます。この方法では、道路の水平線から始まることに変わりはありませんが、より優雅に坂を処理することができるようになります。平坦な道路では、セグメントの位置を追跡する2つの方法は同等であることに注意してください。
このことをいくつかのコードで説明しましょう。
current_x = 160 // Half of a 320 width screen
dx = 0 // Curve amount, constant per segment
ddx = 0 // Curve amount, changes per line

for each line of the screen from the bottom to the top:
  if line of screen's Z Map position is below segment.position:
    dx = bottom_segment.dx
  else if line of screen's Z Map position is above segment.position:
    dx = segment.dx
  end if
  ddx += dx
  current_x += ddx
  this_line.x = current_x
end for

// Move segments
segment_y += constant * speed // Constant makes sure the segment doesn't move too fast
if segment.position < 0 // 0 is nearest
  bottom_segment = segment
  segment.position = zmap.length - 1 // Send segment position to farthest distance
  segment.dx = GetNextDxFromTrack() // Fetch next curve amount from track data
end if
この方法でカーブを描く大きな利点は、カーブの後に直線がある場合、カーブから出るときに直線を見ることができることです。同様に、カーブの後に反対方向のカーブ(あるいは同じ方向の急なカーブ)がある場合、カーブにぶつかる前に、次の線路がカーブを曲がってくるのを見ることができるのです。

この錯覚を完成させるには、地平線のグラフィックが必要です。カーブが近づいても、水平線は変化しない(あるいは少ししかスクロールしない)。そして、カーブが完全に描かれると、車はそれを回り込むと仮定し、水平線はカーブが向いている方向と反対側に素早くスクロールする。曲線が再び直線になると、曲線が完成するまで背景がスクロールし続けます。セグメントを使用している場合は、ベースとなるセグメントの設定に従って地平線をスクロールさせればよいのです。

一般的なカーブの公式

最も単純な道」で説明したカーブ技術について、1つ興味深い見解があります。この観察は、上記の内容よりも数学的なもので、グラフィックエンジンが解像度に依存しないか、丘の章で説明した「3d projected segments」技術を使っている限り、読み飛ばしてもかまいません。

最も単純な道」のセクションの「Z」を使った曲線の例を見てみると、ある線におけるZ位置(またはX位置)は、増加する一連の数値(例えば1 + 2 + 3 + 4)の合計であることがわかります。これは、算術級数または算術級数と呼ばれるものです。1+2+3+4ではなく、2+4+6+8、つまり2*1+2*2+2*3+2*4を足すと、よりシャープなカーブを描くことができる。この場合の「2」は、先ほどの変数segment.dxのことです。また、これを因数分解すると、2(1 + 2 + 3 + 4)となる! あとは、1 + 2 + ... を表す公式を見つけるだけです。+ ここで、Nは曲線を構成する直線の数である。算術級数の和はN(N+1)/2に等しいことがわかる。つまり、式はs = A * [ N(N+1)/2 ]と書くことができる。ここでAは曲線の鋭さ、sは和である。これをさらに変形して、例えば画面下部の道路の中心を始点として加えることができる。これを「x」と呼ぶと、s = x + A * [ N(N+1)/2 ]となる。

これで、曲線を表す公式ができました。ここで問いたいのは、「始点xと曲線のNラインが与えられたとき、曲線が最終的にx-位置's'に到達するためには、Aはどうあるべきか」ということです。Aを解くために方程式をジャグリングすると、A = 2(s - x)/[n(n+1)] となる。つまり、ある曲線の鋭さは、終点のX位置で記憶され、グラフィックエンジンの解像度に依存しないようにすることができるのです。

遠近感のあるステアリング

ステアリングを操作したときに、車のスプライトだけが動くようなゲームでは、見た目が面白くありません。そこで、プレイヤーの車のスプライトを動かすのではなく、画面の中央に置いたまま、道路を動かす、もっと言えば、画面の前(下)にある中心線の位置を動かすようにします。ここで、プレイヤーは常に道路を見ていると仮定して、道路の端を画面の中心にします。そのためには、道路の角度の変数が必要です。そこで、画面中央と道路前面の位置の差を計算し、道路のグラフィックの高さで割ります。そうすると、1行ごとに道路の中心を移動させる量がわかる。


スプライトとデータ

オブジェクトの配置と拡大縮小

スプライトは背面から前面へ描画します。これを「絵描きのアルゴリズム」と呼ぶことがあります。そのためには、各オブジェクトが画面のどこに描かれるべきかをあらかじめメモしておき、別のステップで描画する必要があります。私のやり方は、次のようなものです。Zマップを見ながら道路を描いていくのですが、そのときに、各スプライトが画面のどのラインと関連づけられるかもメモしておきたいのです。新しいZマップの値が読み込まれるたびに、次のスプライトのZ位置が現在のZマップの値よりもカメラに近いか、または等しいかどうかをチェックします。その場合、そのスプライトの画面のY位置は、現在の行に属するものとして記録します。次に、次のスプライトを同じようにチェックします。これを、現在のスプライトよりもZ位置が遠いスプライトをリストからはずすまで続けます。

オブジェクトの X 位置は、道路の中心からの相対的な位置として記録しておく必要があります。スプライトを水平に配置する最も簡単な方法は、現在のラインのスケーリングファクター(Zの逆数)を掛けて、それを道路の中心に追加することです。

トラックデータの保存

最初の道路デモを作ったとき、レベル情報を、指定した距離で発生するイベントのリストとして保存しました。この距離は、もちろんテクスチャの位置単位です。イベントは、カーブを開始したり停止したりするコマンドで構成されています。さて、私が知る限り、道路がカーブを始めたり止めたりする速度は任意である。唯一のルールは、プレイヤーの車のスピードと相関していなければならないようです。

しかし、セグメント化されたシステムを使っている場合は、コマンドのリストを使えばいいのです。各コマンドの所要距離は、見えないセグメント線が画面上をどれだけ速く流れていくかに相当する。また、タイルマップ上で動作するトラックフォーマットを作成することで、ある程度現実的なトラックの地形を表現することができます。つまり、各タイルが1つのセグメントである可能性があります。急カーブなら90度、緩やかなカーブなら45度という具合です。

道路のテクスチャ

さて、道路には、今のような交互の線などではなく、本当のグラフィカルなテクスチャが欲しいと思うでしょう。これを行うには、いくつかの方法があります。安くて簡単な方法は、次のようなものです。道路にいくつかのテクスチャを用意します(交互に並ぶ効果用)。道路の各水平線が描かれるとき、その線の幅に合うようにテクスチャを伸ばします。または、伸ばせない場合は、2つの完全な道路ビットマップのうちの1つから線を選びます(アウトランナーズのようなものです)。

道路をより正確に見せたい場合は、各ラインのZをテクスチャグラフィックの行番号に対応させます。ほら。1 つのテクスチャ道路です。

しかし、もし、交互に色が変わる短冊が欲しいだけなら、答えはもっと簡単です。特に、固定点を使う場合は。各Zについて、ビットの1つを道路の色合い(暗いか明るいか)を表すようにします。そして、そのビットに適した道路のパターンや色を描けばよいのです。

いくつかの三角法

実装に取り​​掛かる前に、いくつかの基本的な三角法を使用して、3D世界のポイントを2D画面に投影する方法を思い出してみましょう。

最も基本的には、ベクトルや行列に入ることなく、3D投影は同様の三角形の法則を使用します。ラベルを付ける場合:

h =カメラの高さ
d =カメラから画面までの距離
z =カメラから車までの距離
y =画面のy座標
次に、同様の三角形の法則を使用して計算できます

y = h * d / z

サイドオンビューではなくトップダウンビューから同様の図を描画し、画面のx座標を計算するための同様の式を導出することもできます。

x = w * d / z

ここで、 w =道路の幅の半分(カメラから道路の端まで)

xとyの両方について、実際に行っているのは次の係数によるスケーリングであることがわかります。

d / z

座標系

これはダイアグラム形式では素晴らしくシンプルに聞こえますが、コーディングを開始すると、変数の命名が少し緩くなり、3Dの世界座標を表すものと2Dの画面座標を表すものが明確でないため、少し混乱しやすくなります。また、実際にはカメラが私たちの車を追いかけているのに、カメラは私たちの世界の原点にあると想定しています。

より正式には、次のようになります。

世界座標からカメラ座標への変換
正規化された投影面にカメラ座標を投影する
投影された座標を物理的な画面(この場合はキャンバス)の座標にスケーリングします


注:真の3Dシステムでは、回転ステップはステップ1と2の間にありますが、カーブを偽造するため、回転について心配する必要はありません。

ゲーム変数

背景画像とスプライト画像に加えて、次のような多くのゲーム変数が必要になります。
これらの一部は、微調整UIコントロールを使用して調整できるため、実行時に重要な値の一部を変更して、レンダリングされた道路にどのような影響があるかを確認できます。その他は、調整可能なUI値から導出され、reset()メソッド中に再計算されます。
var fps           = 60;                      //何秒間に何回「更新」するか how many 'update' frames per second
var step          = 1/fps;                   // 各フレームの長さ(秒) how long is each frame (in seconds)
var width         = 1024;                    // 論理キャンバス幅 logical canvas width
var height        = 768;                     // 論理キャンバスの高さ logical canvas height
var segments      = [];                      //道路セグメントの配列 array of road segments
var canvas        = Dom.get('canvas');       // キャンバス our canvas...
var ctx           = canvas.getContext('2d'); // 描画コンテキスト...and its drawing context
var background    = null;                    // 背景画像(下に読み込まれます) our background image (loaded below)
var sprites       = null;                    // スプライトシート(下に読み込む) our spritesheet (loaded below)
var resolution    = null;                    //解像度独立のためのスケーリングファクター(計算済み) scaling factor to provide resolution independence (computed)
var roadWidth     = 2000;                    //実際には道路の半分の幅、道路が-roadWidthから+roadWidthに広がっている場合、簡単に計算します actually half the roads width, easier math if the road spans from -roadWidth to +roadWidth
var segmentLength = 200;                     // 単線の長さ length of a single segment
var rumbleLength  = 3;                       // 赤/白のランブルストリップのセグメント数 number of segments per red/white rumble strip
var trackLength   = null;                    //z トラック全体の長さ (計算値) z length of entire track (computed)
var lanes         = 3;                       // 車線数 number of lanes
var fieldOfView   = 100;                     //視野角 angle (degrees) for field of view
var cameraHeight  = 1000;                    // z カメラの高さ z height of camera
var cameraDepth   = null;                    // z カメラとスクリーンの距離 (計算) z distance camera is from screen (computed)
var drawDistance  = 300;                     //描画するセグメント数 number of segments to draw
var playerX       = 0;                       // 道路の中心からのプレーヤーの x オフセット (-1 から 1 で roadWidth に依存しない). player x offset from center of road (-1 to 1 to stay independent of roadWidth)
var playerZ       = null;                    // プレイヤーのカメラからの相対的なzの距離(計算) player relative z distance from camera (computed)
var fogDensity    = 5;                       //指数関数的な霧密度 exponential fog density
var position      = 0;                       // 現在のカメラのZ位置(プレイヤーの絶対Z位置を得るためにplayerZを追加します。) current camera Z position (add playerZ to get player's absolute Z position)
var speed         = 0;                       // 現行速度current speed
var maxSpeed      = segmentLength/step;      //  最高速度 (衝突検出を容易にするため、1フレームで1セグメント以上移動できないようにする) top speed (ensure we can't move more than 1 segment in a single frame to make collision detection easier)
var accel         =  maxSpeed/5;             // 加速度-「しっくりくる」までチューニング acceleration rate - tuned until it 'felt' right
var breaking      = -maxSpeed;               // 減速度 deceleration rate when braking
var decel         = -maxSpeed/5;             // 加速もブレーキもかけないときの「自然な」減速率'natural' deceleration rate when neither accelerating, nor braking
var offRoadDecel  = -maxSpeed/2;             // オフロードの減速は、その中間にある off road deceleration is somewhere in between
var offRoadLimit  =  maxSpeed/4;             // オフロードの減速が効かなくなる限界速度 limit when off road deceleration no longer applies (e.g. you can always go at least this speed even when off road)

一時メモ

検索キーワード

  • FZRO Like
  • Fake3D
  • pseudo 3d(2.5次元)
  • SFCのマリオカートやF-Zeroの様なスプライトで擬似3D表現をするにはどうすれば良いのか?
    • レトロゲーム再現 スーパーファミコンの疑似3D ゲーム・プログラミング JavaScriptサンプル

テスト

  • 画面サイズは640×480にする
  • チップサイズは32×32にする
    • 上記の画面ならチップは「20×15」敷き詰める事ができる

事前

  • 画面サイズ
global.Window_Width = window_get_width()
global.Window_Height = window_get_height()
  • タイルチップのサイズ
  • 横方向の敷き詰める事ができるタイル数
  • 縦方向の敷き詰める事ができるタイル数
  • 自機の移動速度
  • 消失点(アイレベル)のY座標

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

【メニュー編集】

スカイリム関連

スカイリム関連


Menu

【メニュー編集】

スクリプト関連

フリーエリア

管理人/副管理人のみ編集できます