画面外のオブジェクトを指す画面の端に矢印を描画するにはどうすればよいですか?


12

このトピックで説明されていることを実行したいと考えています。

http://www.allegro.cc/forums/print-thread/283220

ここで述べたさまざまな方法を試しました。

まず、Carrus85で説明されている方法を使用しようとしました。

2つの三角形の斜辺の比を取るだけです(もう一方の三角形を使用しても構いません。計算する距離としてポイント1とポイント2をお勧めします)。これにより、大きな三角形からコーナーの三角形のアスペクト比のパーセンテージが得られます。次に、deltaxにその値を掛けてx座標のオフセットを取得し、deltayにその値を掛けてy座標のオフセットを取得します。

しかし、オブジェクトが画面の端からどれだけ離れているかを計算する方法を見つけることができませんでした。

次に、23yrold3yroldによって提案されたレイキャスティング(これまで行ったことのない)を使用してみました。

画面の中心からオフスクリーンオブジェクトに光線を発射します。光線が長方形のどこで交差するかを計算します。あなたの座標があります。

最初に、2つのポイントのx位置とy位置の差によって形成される三角形の斜辺を計算しました。これを使用して、その線に沿って単位ベクトルを作成しました。x座標またはy座標のいずれかが画面外になるまで、そのベクトルをループしました。2つの現在のxとyの値は、矢印のxとyを形成します。

これが私のレイキャスティングメソッドのコードです(C ++およびAllegro 5で記述されています)

void renderArrows(Object* i)
{
    float x1 = i->getX() + (i->getWidth() / 2);
    float y1 = i->getY() + (i->getHeight() / 2);

    float x2 = screenCentreX;
    float y2 = ScreenCentreY;

    float dx = x2 - x1;
    float dy = y2 - y1;
    float hypotSquared = (dx * dx) + (dy * dy);
    float hypot = sqrt(hypotSquared);

    float unitX = dx / hypot;
    float unitY = dy / hypot;

    float rayX = x2 - view->getViewportX();
    float rayY = y2 - view->getViewportY();
    float arrowX = 0;
    float arrowY = 0;

    bool posFound = false;
    while(posFound == false)
    {
        rayX += unitX;
        rayY += unitY;

        if(rayX <= 0 ||
            rayX >= screenWidth ||
            rayY <= 0 ||
            rayY >= screenHeight)
        {
            arrowX = rayX;
            arrowY = rayY;
            posFound = true;
        }               
    }

    al_draw_bitmap(sprite, arrowX - spriteWidth, arrowY - spriteHeight, 0);
}

これは比較的成功しました。オブジェクトが画面の上下にある場合、画面の右下に矢印が表示されます。矢印が描かれている場所が画面の中心を中心に180度回転しているように見えます。

これは、三角形の斜辺を計算しているときに、xの差またはyの差が負であるかどうかに関係なく、常に正であるという事実によるものだと思いました。

考えてみると、レイキャスティングは問題を解決する良い方法とは思えません(sqrt()と大きなforループを使用する必要があるため)。

回答:


6

したがって、2つの座標またはベクトルがあり、1つは画面の中心(これからC)、もう1つはオブジェクト(これからP)です。

数学を知っていれば、線は原点と方向ベクトルとして表現できることを知っているかもしれません。原点は画面の中心であり、方向ベクトルはPからCを引いた値を見つけることができます。この式は、基本的に同じパラメトリック形式でも表現できます。

x = (P.x - C.x)t + C.x;
y = (P.y - C.y)t + C.y;

(P.? - C.?)ビットを参照してください?それがあなたの方向ベクトルです(私が言ったように、PからCを引きます)。最後のC.?ビットはラインの原点です。

t変えることができ、変数である010ベクトルの原点と(あなたが作動した場合、xおよびyなるwoulld C.xC.y)、1あなたのオブジェクトを操作し、再び(座標であること、それはなるだろうP.xP.y、あるいはベクトルの「終わり」必要に応じて)、セグメントの両端間を補間する間の値。また、外側の値を割り当てることもできます。下0ではベクトルの方向を反転させ、上1では同じ方向にベクトルをさらに「拡張」します。

これを取得すると、非常に簡単になります。あなたの目的は、(このベクトルのポイントを見つけるためにあるxyの与えられた値のためにt)ここで、X=WIDTHまたはY=HEIGHT最初に来るものは何でも、。ご覧のとおり、tここで唯一の変数です。

(0)
WIDTH = (P.x - C.x)t + C.x;
and
HEIGHT = (P.y - C.y)t + C.y;

またはそれを再表現する:

(1)
t = (WIDTH - C.x)/(P.x - C.x)
and
t = (HEIGHT - C.y)/(P.y - C.y)

これにより、右境界線と上境界線でベクトルによって定義された線の切断点が取得されます。同じことが画面の左と下の境界にも当てはまります。ここ0ではWIDTH、とではなく、両方のケースをチェックする必要がありますHEIGHT

最終的には画面外でも境界が切り取られるため、最低t値は最初の連絡先になります。操作を逆にして、見つかったt値を式(0)(両方に同じ値!)に適用すると、新しい(x,y)が得られます。これが切断座標になります。

問題には数学エラーや実装の違いがあるかもしれませんが、それは基本的な考え方です。私もいくつかの部品を省きました(常に4つのケースがあり、1つだけが必要です)が、少し考えれば最終的な解決策が得られます:)


ありがとう。やってみます。編集:好奇心から、この方法はCarrus85が記述したものであると思いますか(斜辺の比率を使用して)?
アダムヘンダーソン

1
@AdamHenderson喜んでお手伝いします:)後で矢印を描くことができるように、方向ベクトルを保持できることを忘れないでください。それを正規化して、単一方向ベクトルを取得arrow-lengthし、切断ベクトル「et voila」からそれを数回引くと、矢印の始点と終点が得られます。
kaoD

1
@AdamHendersonは視覚的には同じことです。なぜなら、あなたのラインは彼が話している斜辺だからです。実際には、彼の提案には角度(および三角法)が関係しているため、これは同じではありません。これには、三角形はまったく関係しません(ただし、ベクトルは斜辺がベクトルで、両側がxおよびyコンポーネントである三角形と考えることができます)
。-kaoD

再度、感謝します!矢印を正しい方向に向けるという私の次の問題を解決しました。
アダムヘンダーソン

1
@AdamHendersonうん、軸が反転した場合は下。ところで、今後の参考のために、Allegroのフォーラムにこの質問へのリンクを投稿することをお勧めします。
kaoD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.