2Dスクリーン座標とデカルト座標の違いに対処する方法


23
  • ほとんどの2D画面/ビットマップ座標系には、下向きの正のY軸があります(原点は左上隅にあります)。
  • これは、正のY軸を上に向け(原点を中心に)ほとんどの人が幾何学的に考える方法とは逆です。

ほとんどのゲームは、2つの異なる2D座標系をどのように管理しますか?座標には主に2つのタイプ(画面とデカルト)がありますが、スプライト空間、ワールド空間、ビュー空間、画面空間など、さまざまな座標空間があります。

バックグラウンド:

私はもともと、ゲーム内の世界座標を2Dスクリーン座標規則に一致させました。これにより、グラフィックス描画ルーチンを使用することは非常に自然になりましたが、atan2()などの三角関数を使用すると微妙な問題が発生しました。atan2()が正のy軸が上を向いていると想定するため、atan2()2Dスクリーン座標の供給結果は非常に紛らわしいです。

そこで、世界座標を古典的なデカルト座標系(画面の左下に原点がある)に変更しました。atan2()を使用した推論ははるかに簡単ですが、現在では他の種類の推論を行うことが難しくなっています。

  • ここで画面をクリックすると、その下にあるスプライトは何ですか?
  • そのスプライトはどこでクリックしましたか?
  • スプライトが間違った位置に描画された場合、間違って計算されたものは何ですか?画面座標または世界座標?

画面からデカルト座標への変換では、両方の(x、y)値のオプションの変換を使用して、y値を-1でスケーリングするだけです。ゲームデザインのベストプラクティスにもっと興味があります。

  • ほとんどのゲームは、単に画面座標の規則に固執し、atan2()のようなものがどのように機能するかについての考え方を変えますか?
  • 座標系の変換はいつ/どのように行われますか?(マトリックス、OOP抽象化などを使用)
  • スプライトの位置は、スプライトの中心または角の1つとして保存されていますか?「間違った」方向に進むスプライトの高さ/幅は、描画するときによくある問題のようです。

私の質問は主に2Dゲームに関するものですが、OpenGLはY軸が上を向く座標系を使用しているようです。OpenGLは、最終的にこれらの3D座標を2Dスクリーン座標系に投影する必要があります。おそらくいくつかのガイダンスはOpenGLの方法で見つけることができます...

回答:


8

考えられるすべての方法を試してみましたが、純粋に2Dゲームであり、画面描画システムを使用するだけで、あなたの生活がはるかに楽になることがわかりました。Sin、Cos、およびatan2は少し異なる方法で使用する必要がありますが、この不便さは、上下、時計回り、反時計回りのどちらであるかが簡単にわかるため、簡単に補うことができます。また、2Dゲームの場合はメートルではなくピクセルで作業することをお勧めします。画面上の距離を考えるのははるかに簡単です。また、ゲーム全体のスケールを変更する可能性はほぼゼロです。

「ほとんどのゲームは2つの異なる2D座標系をどのように管理しますか?」

  • ほとんどの2Dゲームはスクリーンシステムを使用するソースを見てきましたが、各エンティティはそのワールドスペースを知っている必要があります。描画マネージャーにこれをスクリーン位置に変換させます。この時点で、必要なマトリックス変換を実行します。

「スプライトの位置は、スプライトの中心または角の1つとして保存されていますか?」

  • 中心から作業する場合は、回転がよりまっすぐになりますが、角も知っておくと便利です。

「おそらく、OpenGLのメソッドにいくつかのガイダンスがあります...」

  • 3Dエンジンはまったく別のケースです。真のカメラがあるため、画面の位置は世界の位置とは大きく異なる場合があります。トップダウンゲームでは、X軸とY軸ではな​​く、X軸とZ軸で作業します。

1

私はここで物事を単純化しすぎているかもしれませんが、私の傾向は、2D / UIサブシステムが「スクリーン」座標と呼ばれるものに厳密に対処することです。ScreenToCartesianTransformとCartesianToScreenTransformの2つのマトリックスがあります。マウス入力イベントを受け取ると、CartesianToScreenTransformを使用してマウス座標が変換されてから、2D / UIシステムの入力マネージャーに渡されます。そこから、UIシステムは画面座標系を使用してヒットテストを実行し、それに応じてイベントを処理します(または処理しません)。マウス入力イベントが2D / UIによって処理されない場合、元の変換されていない座標を使用して3Dシステム(存在する場合)に渡すことができます。

2D / UIシステムは「スクリーン」座標でのみ処理するため、レンダリングエンジンで処理する前に、そのジオメトリをScreenToCartesianTransformで変換する必要があります。


実際、使用しているツールキットによっては、マウス入力イベントが既に画面座標にある場合があります。その場合、2D / UIシステム用に変換するのではなく、3Dシステム(存在する場合)用に変換します。
マイクストロベル

0

Flashのような表示ツリーを使用することを好みます。ルートノード(ゲームビュー)には、ワールドの子(ワールドノード)と、HUDの子が含まれます。ワールドノード内には、ゲームワールド内のオブジェクトのノードがあります。

次に、ワールドノードを単純に変換します。平行移動(カメラのパン)および比例スケーリング(カメラのズーム)とともに、他の2つの変換も適用します。

  • 座標系を反転する-1 yスケール。
  • 世界単位(メートル)を画面単位(ピクセル)に変換するスケーリング

次に、ゲームオブジェクト描画コードでy-up /ワールド座標を使用し、HUD描画コードでy-down /スクリーン座標を使用します。どちらも非常に自然な感じです。

「どのオブジェクトをクリックしているのか」などの質問に答えるために、表示ノードメソッドを使用して、座標系間で座標を変換します(globalToLocalFlashの場合やその逆など)。

ちなみに、atanyが下がっているときに実際に異なる動作をするわけではありません。すべての角度を反時計回りではなく時計回りに考える必要があります。


0

OpenGLは、DirectXと同様に、水平面に沿ってX軸とZ軸を持ち、Yは上を向いています。
画面座標に問題は一度もありませんでした。最も簡単な方法は、単純にそれをどのように扱うかだと思います。atan2などの何かが気に入らない場合は、供給されるパラメーターを変更します。

シーングラフなどの相対座標またはローカル座標を使用している場合は、ToGlobalCoords()などの単純な関数が適しています。実際、空間配置、シーングラフ、およびlocalToGlobalの詳細を知りたい場合、Game Engine Architectureからの抜粋はそれについてです。

スプライトは、左上隅または(0,0)原点から描画されます。理由は、ウィンドウの左上の原点によるものです。

ウィンドウの座標系を変更するのは少しばかげているようで、ほとんどのゲームでトリガーよりも大きな役割を果たす入力のようなものを、かなり難しくします。また、コードの規範やユーザーからあなたを遠ざけます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.