화면 가장자리에 화면 밖에있는 개체를 가리키는 화살표를 그리는 방법은 무엇입니까?


12

이 주제에 설명 된대로 수행하고 싶습니다.

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

여기에 언급 된 다양한 방법을 시도했습니다.

먼저 Carrus85에서 설명한 방법을 사용하려고했습니다.

두 삼각형 빗변의 비율을 취하십시오 (다른 삼각법에 관계없이 상관없이 계산하는 거리로 포인트 1과 포인트 2를 제안합니다). 그러면 더 큰 삼각형에서 모서리에있는 삼각형의 종횡비 비율이 표시됩니다. 그런 다음 간단하게 deltax에 해당 값을 곱하여 x 좌표 오프셋을 얻고 해당 값을 deltay하여 y 좌표 오프셋을 얻습니다.

그러나 물체가 화면 가장자리에서 얼마나 떨어져 있는지 계산하는 방법을 찾지 못했습니다.

그런 다음 23yrold3yrold가 제안한 레이 캐스팅 (이전에 해본 적이없는)을 사용해 보았습니다.

화면 중앙에서 오프 스크린 물체로 광선을 발사합니다. 사각형에서 광선이 교차하는 위치를 계산하십시오. 당신의 좌표가 있습니다.

먼저 두 점의 x 및 y 위치 차이로 형성된 삼각형의 빗변을 계산했습니다. 나는 이것을 사용하여 그 선을 따라 단위 벡터를 만들었습니다. x 좌표 또는 y 좌표가 화면에서 벗어날 때까지 해당 벡터를 반복했습니다. 두 개의 현재 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

따라서 두 개의 좌표 또는 벡터가 있습니다. 하나는 화면의 중심 (지금부터 C)이고 다른 하나는 객체 (지금부터 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다를 수있는 변수 01, 0벡터의 기원 인 (당신이 작동 할 경우, 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두 경우 모두,하지 않는 WIDTHHEIGHT.

결국 화면 밖에서도 경계선을 자르기 때문에 가장 낮은 t값이 첫 접촉점이됩니다. 연산을 취소하고 찾은 t값을 방정식에 적용 하면 (0)(두 값 모두 동일) 새로운 (x,y)좌표가 생성됩니다.

문제에 대한 수학 오류나 구현 차이가있을 수 있지만 이것이 기본 아이디어입니다. 나는 일부 부품도 생략했습니다 (항상 4 가지 절단 사례가 있으며 하나만 필요합니다).하지만 약간의 생각으로 최종 솔루션을 얻을 수 있습니다. :)


감사. 나는 그것을 줄 것이다. 편집 : 호기심에서,이 방법이 Carrus85가 묘사 한 방법이라고 생각합니까 (가설의 비율을 사용하여)?
Adam Henderson

1
@AdamHenderson 도와 드리겠습니다. :) 나중에 화살표를 그릴 수 있도록 방향 벡터를 유지할 수 있습니다. 당신은 단일 방향 벡터를 얻기 위해 정규화 할 수 있습니다 arrow-length, 절단 벡터 "et voila"에서 시간을 빼고 , 당신은 화살표의 출발지와 목적지를 가지고 있습니다.
kaoD

1
@AdamHenderson 시각적으로 똑같습니다. 선이 그가 말하는 빗변이기 때문입니다. 그의 제안에 각도 (및 삼각법)가 관련되어 있기 때문에 실제로는 동일하지 않습니다. (당신은 빗변이 벡터는 삼각형로 벡터 생각할 수있는 양면이 있지만 이는 전혀 삼각형을 포함하지 않는 xy구성 요소.)
kaoD

다시 감사합니다! 화살표를 올바른 방향으로 가리키는 다음 문제를 해결했습니다.
Adam Henderson

1
@AdamHenderson yep, 축이 뒤집어지면 아래쪽. BTW, 나중에 참조 할 수 있도록 Allegro의 포럼에이 질문에 대한 링크를 게시하는 것이 좋습니다.
kaoD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.