9

このゲームのように、回転を処理する無限/繰り返しの世界を作成するにはどうすればよいですか?

http://bloodfromastone.co.uk/retaliation.html

次のような階層を使用して、回転する移動する世界をコーディングしました。

シーン
  -mainLayer(CCLayer)-rotationLayer(CCNode)-positionLayer
     (
        CCNode)

rotationLayerとpositionLayerのサイズは同じです(現在4000x4000ピクセル)。

私はrotationLayerを回転させて全世界を回転させ、positionLayerを移動して全世界を移動します。これにより、プレーヤーは常にデバイス画面の中央に留まり、移動して回転するのは世界です。

ここで、プレーヤーが世界の境界に到達した場合(世界が移動して、世界の境界がデバイスの画面の境界に接触するようになる)、世界が反対の境界に「ラップ」されるようにします。世界が無限になるように。世界が回転していなければ、それは簡単ですが、今では回転しているので、これを行う方法がわかりません。私は数学と数学の考え方がばかなので、ここで助けが必要です。

今、私はここでcocos2d-iphone関連のヘルプは必要ないと思います。私が必要としているのは、プレーヤーが世界の境界の外にいるかどうかを計算する方法と、世界を包むために世界に与えなければならない新しい位置を計算する方法です。

正方形の世界の中で私の鋳造所となる円の半径を計算する必要があると思います。正方形の世界がどの角度にあっても、表示される長方形(画面)が常に境界の内側にあることが保証されます。ワールドスクエア。次に、表示されている長方形の境界が境界円の外側にあるかどうかを計算する方法が必要です。その場合、世界を移動する境界円の新しい反対の位置を計算する方法が必要です。説明のために、5つの画像を追加しました。

回転した正方形の世界の内側の境界円の内側にある目に見える長方形:
回転した正方形の世界の内側の境界円の内側にある目に見える長方形

回転した正方形の世界の内側にある、目に見える長方形のヒット境界円の上部:
ここに画像の説明を入力してください

回転した正方形のワールドが反対の垂直位置に移動したため、表示されている長方形の下部が回転したワールド内の境界円に当たるようになりました。
ここに画像の説明を入力してください

別のシナリオを説明するために、回転した正方形の世界の内側にある、表示されている長方形の上部のバウンズサークルの別の例:
ここに画像の説明を入力してください

そして、再び回転した正方形の世界が反対の垂直位置に移動し、表示されている長方形の下部が回転した世界の内側の境界円に当たるようになりました。
そして、再び回転した正方形の世界が反対の垂直位置に移動し、表示されている長方形の下部が回転した世界の内側の境界円に当たるようになりました

回転していない状況でpositionLayerを移動することは、世界が回転しない限りこれを理解できると言ったので、私が理解した数学ですが、回転します。移動/配置されるワールド/CCNode(positionLayer)は、回転されるワールド/ CCNode(rotationLayer)内にあります。回転するrotationLayerのアンカーポイントは常に画面の中央にありますが、移動するpositionLayerは回転するrotationLayerの内側にあるため、rotationLayerのアンカーポイントを中心に回転します。そして、私は迷子になります...たとえば、positionLayerを十分に下に移動して、その上部の境界線が画面の上部に当たる場合、JohnPSが説明するように、そのpositionLayerをラップする必要がありますが、それほど単純ではありません。ベクターベースでラップする必要があります。 rotationLayerCCNodeの回転について。これはどうしたらいいかわかりません。

ありがとう
Søren

4

3 に答える 3

7

ジョンが言ったように、最も簡単な方法は、トーラス ワールドを構築することです。あなたの船がドーナツの表面上の点であり、表面上でしか移動できないと想像してください. 2 つの円 (図の赤と紫) が交差するポイントにいるとします。

トーラス上の円.

それらのサークルをたどると、最初の場所にたどり着きます。また、表面上をどのように移動しても、「エッジ」に到達する方法はないことに注意してください。トーラスの表面にはそのようなものがないため、無限の 2D ワールドとして使用すると便利です。便利なもう 1 つの理由は、方程式が非常に単純であることです。トーラスのどこにいるかを 2 つの角度で指定します。赤い円を見つけるために紫色の円の「原点」から移動する角度と、関心のある点を見つけるために赤い円を移動する角度です。どちらも角度は 360 度でラップします。theta2 つの角度を と と呼びましょうphi。それらは世界におけるあなたの船の座標であり、速度を変更したときに変更するものなどですxyただし、モジュラスを変更するときは常にモジュラスを使用する必要があります (世界は各方向に 360 度しかなく、ラップアラウンドします)。

あなたの船が座標(theta_ship,phi_ship)にあり、向きがあるとしますgamma_ship。船が中心にあり、長さ/幅が全世界の n パーセンテージに等しい正方形の窓を描きたいとします (一度に世界の 4 分の 1 だけを見たい場合n = sqrt(1/4) = 1/2は、に設定されたウィンドウの長さと幅n*2*pi = pi)。xこれを行うには、スクリーン座標 (および) で表されるポイントを取得し、ワールド座標 (および)yでポイントを吐き出す関数が必要です。たとえば、世界のどの部分に対応するかを尋ねた場合、船の座標を返す必要があります。船の向きがゼロの場合 (とはとthetaphi(0,0)(theta_ship,phi_ship)xythetaphi) 次に、ある座標(x_0,y_0)は に対応します(theta_ship+k*x_0, phi_ship+k*y_0)。ここで、は、画面で見ることができる世界の量ととkの境界に関連する倍率です。ローテーション byは、以下の関数で説明する少しのトリガーを導入します。量の正確な定義については、図を参照してください。! 青は画面座標系、赤は世界座標系と構成変数 (世界のどこに船があるかを表すもの) です。ワールド座標で表されるオブジェクトは緑色です。xygamma_ship

座標変換関数は次のようになります。

# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
    # this is the angle between the (x,y) vector and the center of the screen           
    alpha = atan2(x,y); 
    radius = sqrt(x^2 + y^2); # and the distance to the center of the screen

    # this takes into account the rotation of the ship with respect to the torus coords
    beta = alpha - pi/2 + gamma_ship;

    # find the coordinates
    theta = theta_ship + n*radius*cos(beta)/(2*pi);
    phi = phi_ship + n*radius*sin(beta)/(2*pi));

    # return the answer, making sure it is between 0 and 2pi
    return (theta%(2*pi),phi%(2*pi))

それだけだと思います。数学は比較的簡単なトリガーにすぎません。それが正しいことを自分自身に納得させるために、少し図を作成する必要があります。あるいは、回転行列とその兄弟である剛体変換 (特別なユークリッド群 SE(2))を使用することで、より自動化された方法で同じ答えを得ることができます。後者については、オンラインで無料のMurray, Li, Sastryの最初の数章を読むことをお勧めします。

反対のことをしたい場合 (ワールド座標からスクリーン座標に移動する) は、多かれ少なかれ同じことをする必要がありますが、逆になります:

beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
于 2011-11-18T21:42:27.360 に答える
2

「反対の境界」が何を意味するかを定義する必要があります。2 次元の例については、基本ポリゴンを参照してください。正方形の辺を反対側にマッピングするには 4 つの方法があり、球、実射影平面、クライン ボトル、またはトーラスを取得します。古典的なアーケード ゲームのAsteroidsには、実際にトーラスのプレイ面があります。

アイデアは、各境界点を、意味があり一貫した他の境界点に接着する必要があるということです。

あなたの世界が真に 3 次元である場合 (2-D サーフェス マップ上の 3-D だけではない)、エッジをどのように接着するかを決定する作業がかなり難しくなると思います。エッジはサーフェスに埋め込まれています。三次元の世界で。

編集:

2D マップがあり、小惑星のように回り込みたいとします。

マップが1000x1000ユニットの場合、マップx=0の左の境界線がx=999右の境界線であり、右を見ていると20前方のユニットが見えます。では、x=995まで見たいのです1015が、これは地図の右側から外れているので、 になる1015はず15です。

あなたがx=5左の20ユニットにいて見るx=-15と、あなたが本当になりたいものがわかります985.

マップの境界を越えて見ているときにこれらの数値 (常に 0 から 999 の間) を取得するには、モジュロ演算子を使用する必要があります。

new_x = x % 1000; // in many programming languages

が負の場合x、各プログラミング言語は の結果をx % 1000異なる方法で処理します。実装定義にすることもできます。つまり、常に正であるとは限らない ( と の間0)999ため、これを使用する方が安全です。

new_x = (x + 1000) % 1000; // result 0 to 999, when x >= -1000

したがって、ビューを移動または変更するたびに、位置の座標とビュー内の座標を再計算する必要があります。この操作を適用して、xy座標の両方のマップ上の座標を取得します。

于 2011-11-11T19:49:53.233 に答える
0

私はCocos2dを初めて使用しますが、フレームワークの質問ではないので、ジオメトリ計算の問題を解決するために試してみることができると思います。

まず、使用しているすべてのレイヤーのアンカーポイントをそれらすべてのビジュアルセンターに設定することから始めます。

次に、エッジに接触する最初の部分が常にコーナーであるという仮定に同意しましょう。

円の内側にあるかどうかを確認したい場合は、4つのエッジすべてが円の内側にあるかどうかを確認してください。

どのエッジが円の円周に接しているかを知りたい場合は、アンカーが中心にあるため、ポイントx = 0 y=0から最も遠いエッジを確認してください。

アンカーを中央に配置しない理由がある場合は、すべてに各オブジェクトの幅の半分を含める限り、同じロジックを使用できます。

于 2011-11-18T10:37:53.743 に答える