15

これを尋ねる前に、私はネットでたくさんの検索をしました。できません。理解するのは少し難しいです。では、ワールドポジションのボディに対応する正しい画面位置に画像を描画するにはどうすればよいですか?ありがとう。

他の誰かが同じ障害物の前でhimslefを見つけた場合、私はHOW TOを投稿しました、normalocityの良い説明に感謝します。あなたはここでそれを見つけることができます:http://romeo.akademx.ro/2012/04/06/slick-and-box2d/

これはレンダリング関数です:

public void render(GameContainer container, StateBasedGame game, Graphics g)
        throws SlickException {
    g.setBackground(Color.white);

    g.pushTransform();
    g.translate(worldToScreen(body.getPosition()).x, worldToScreen(body.getPosition()).y);
    g.rotate(15, 15, (float) Math.toDegrees(body.getAngle()));
    part.draw();
    g.popTransform();

    g.drawString("Count: " + cont, 5, 40);
    //world.drawDebugData();
}

そして、これらは私が世界画面の調整を変換するために使用する機能です:

public Vec2 screenToWorld(Vec2 screenV) {
    return new Vec2((screenV.x - offset.x) / scaleFactor, yFlip
            * (screenV.y - offset.y) / scaleFactor);
}

public Vec2 worldToScreen(Vec2 worldV) {
    return new Vec2(worldV.x * scaleFactor + offset.x, yFlip * worldV.y
            * scaleFactor + offset.y);
}

私はまた、このリンクにあるSlickDebugDrawを使用しています:http ://slick.javaunlimited.net/viewtopic.php?f = 19&t = 3610&sid = 69614ac53aaf5724b808b75173e8e48e

しかし、彼のDebugDrawは、私のレンダリング関数とはまったく別のものを描画します。私は少し混乱しています。

4

1 に答える 1

67

2D ワールドでスプライトを描画するだけの場合は、基本的に、どのスプライトを画面上に描画し、画面上のどこに描画するかを決定するために追跡する必要があることが 2 つあります。スプライトは世界の特定の場所に存在すると考える必要があり、画面に表示されるものは、ある領域に焦点を当てた世界の 1 つのビューにすぎないと考える必要があります。

追跡する必要があるのは、次の 2 つのことです。

  1. 各スプライトはワールド内に位置する必要があります
  2. あなたの「カメラ」は、世界に対するその位置を追跡する必要があります。

ですから、2D 座標 (x, y) 空間が 1,000,000 x 1,000,000 ピクセルの大きな世界があるとしましょう (ここでは測定単位としてピクセルを使用していますが、これは任意の選択であり、サイズは世界は問題ではありません、私は大きなものを選んだだけです)。次に、その世界に向けられた「カメラ」があり、そのカメラのビューが画面に表示されるとしましょう。カメラが提供するディスプレイのサイズは 1024x768 ピクセルです。

また、矢印キーを使用してそのカメラを世界中に移動するとします。

したがって、世界の座標空間は次のように画面にマップされます。

(0, 0)        +x
      +------------------>
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
     \ /

スプライトが「右」に移動すると、x座標が増加します。「左」に移動すると、x座標が減少します。「上」に移動すると座標が減少し(モニター表示では下に増加するため)、「下」に移動するとスプライトの座標が増加します。yyy

繰り返しますが、画面に表示されるのはカメラの世界観です。では、カメラの左上隅が にあるように設定しましょう(x=500, y=500)。それは次のようになります。

(0, 0)        +x
      +---------------------------------->
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
      |
      |         +===================+
      |         |     the area      |
      |         |  that the camera  |
      |         |    "sees" and     |
      |         |   shows on your   |
      |         |       screen      |
      |         +===================+
     \ /

その設定で、カメラが (500, 500) にあるとします (つまり、この例に示すように、カメラのビューの左上隅はワールド座標 (500, 500) にあります)。 camera は、サイズが 1024x768 の領域を示し、反対側の右下隅は (500+1024, 500+768) =(x=1524, y=1268)です。

私たちの世界のスプライトは、そのカメラのビュー領域内にないことに注意してください。つまり、カメラのビューを画面にレンダリングすると、スプライトは表示されません。

代わりに、カメラが (200, 200) に移動した場合、カメラのビュー エリアは、左上 @ (200, 200) から右下 @ (1224, 968) までのワールド座標をカバーし、何かに見えます。このような:

(0, 0)        +x
      +---------------------------------->
      |   
   +y |  +===================+
      |  |                   |
      |  |   * <= sprite     |
      |  |                   |
      |  |                   | <= camera's view of the world
      |  +===================+
      |
      |
      |
      |
     \ /

カメラがこの位置にある場合、スプライトが表示されます。スプライトが @ (500, 500) で、カメラが (200, 200) の場合、スプライトを画面に描画すると、スプライトは画面上の座標 300, 300 に表示されます。

なんで?

これが実際にあなたの質問への答えです。画面上で物を描く場所は、スプライトのワールド位置(500, 500) からカメラの位置(200, 200) を引いたもので、(300, 300) に等しいからです。

したがって、確認するには:

矢印キー(またはマウス、またはその他の必要な制御スキーム)を使用してカメラの位置を世界中に移動し、スプライトの位置を取得してカメラの位置を差し引くことにより、カメラの位置に対するスプライトの位置をレンダリングします。得られるのは、スプライトが表示される画面座標です。

しかし、もう1つのことがあります...

世界中のすべてのスプライトを描画するのは非常に非効率的です。カメラのビュー内にあるスプライトのみを描画する必要があります。そうしないと、画面に表示されないものを描画することになり、レンダリング/CPU/GPU 時間が無駄になります。

そのため、カメラのビューをレンダリングするときは、スプライトを反復処理して、それらが「カメラ上」にあるかどうか (つまり、それらがカメラのビュー内にあるかどうか) を確認し、描画のみを行う必要があります。それらがこのビュー内にある場合。

そのためには、カメラのサイズ(この例では 1024x768) を取得し、スプライトの位置がカメラのビューの四角形 (カメラの左上の位置) 内にあるかどうかを確認する必要があります。角に加えて、カメラの幅と高さ。

したがって、カメラが 1024x768 ピクセルのサイズのビューを表示し、その左上隅が (200, 200) である場合、ビューの四角形は次のようになります。

(200, 200)                      (1224, 200)
           +===================+
           |                   |
           |    *              |
           |                   |
           |                   |
           +===================+
(200, 968)                      (1224, 968)

スプライトの位置 @ (500, 500) は、この場合、カメラのビュー内にあります。

さらに例が必要な場合は、 Pedestriansと呼ばれる Slick2D の実用的な技術デモがあり、コードを見ることができます。レンダリングする必要がある世界の領域を計算する方法の詳細については、このファイルrender内のメソッドを見て、描画するスプライトの領域を制御する、、、、変数に特に注意してください。また、私のスプライト (または「歩行者」) は に存在するため、1 ピクセルのサイズではなく、独自の幅と高さを持っていることにも注意してください。これにより、何を描画するかを決定する方法が少し複雑になりますが、基本的には、「カメラのビュー内にあるものを描画し、エッジの周りに少し余分に描画する」ことになります。startXstartYstopXstopYTileMap

Pedeestrians リポジトリを自分のマシンに複製し、他の Slick2D プロジェクトと同じ依存関係をプロジェクトに追加して機能させ、何が起こっているかを理解するまでレンダリング コードを再生/変更します。練習と研究を通じてのみ、これがどのように機能するかについてすべての詳細を知ることができます。幸いなことに、この基本的な 2D ワールド対カメラ メソッドを使用してレンダリングを行う方法を理解すれば、すべての 2D アプリのグラフィックスをレンダリングする方法をほぼ理解できるようになります。これは、概念がすべての言語に翻訳されるためです。

また、私の YouTube チャンネルには、歩行者が走っているさまざまなビデオがあります(最も関連性の高いビデオはおそらくこれで、基本的な歩行者がレンダリングされ、カメラが動き回っている様子を示しています)。最初にプロジェクトをビルドします。

于 2012-04-04T14:23:39.123 に答える