클릭 앤 드래그 동작을 영역으로 제한하는 방법은 무엇입니까?


11

다소 일반적인 제목으로 사과드립니다. 나는 내가하려는 일을 성취하는 방법에 대한 많은 단서가 없기 때문에 가능한 해결책을 연구하기조차 어렵습니다.

나는 일종의 경로 마커를 구현하려고합니다 (가장 적합한 이름이있을 수 있지만 이것이 내가 얻을 수있는 최선입니다).

플레이어 앞에는 경로 계획이 있으며, 플레이어는 자신의 턴 계획을 마치면 플레이어가 어떻게 움직일지를 결정합니다. 플레이어는 마커를 클릭하고 선택한 위치로 드래그 할 수 있지만 마커는 정의 된 작업 영역 (회색 비트) 내에서만 이동할 수 있습니다.

경로 마커 다이어그램

그래서 지금 두 가지 문제가 있습니다.

우선, 그 실행 가능한 영역을 어떻게 정확하게 정의해야합니까? 플레이어를 작동 가능한 각도를 형성하는 시작점으로 사용하는 두 개의 벡터를 상상할 수 있습니다. 아마도 두 개의 호는 플레이어가있는 중심이있는 원에서 나올 수 있습니다. 함께.

둘째, 마커를 배치 할 수있는 영역을 정의한 후 마커가 해당 영역 내에서만 유지되도록하려면 어떻게해야합니까? 예를 들어 플레이어가 마커를 클릭하고 드래그하면 작업 영역 내에서 자유롭게 이동할 수 있지만 영역의 경계를 벗어나서는 안됩니다. 예를 들어 플레이어가 마커를 위쪽으로 드래그하기 시작하면 작업 영역의 끝 부분에 닿을 때까지 위쪽으로 이동하지만 (아래의 첫 번째 다이어그램) 플레이어가 옆으로 드래그하기 시작하면 마커가 여전히 드래그를 따라 가야합니다. 영역 내 (아래의 두 번째 다이어그램).

첫 번째 다이어그램 : 위로 이동 두 번째 다이어그램 : 드래그

나는 이것이 너무 혼란스럽지 않기를 바랍니다. 고마워요

편집 : 이것이 차이가 나는 경우 Marmalade SDK와 함께 C ++을 사용하고 있습니다.


나는 당신이 찾고있는 용어가 "waypoint"라고 생각하고 회색 영역을 수학적으로 정의 할 수 있습니까? 문제에 대한 해결책은 아마도 훨씬 쉬울 것입니다.
John McDonald

길 찾기 및 이와 관련된 고개 웨이 포인트? 또한 회색 영역을 수학적으로 정의하는 것은 내 문제 중 하나입니다 .PI는 사각형이나 원과 같은 것을 알아낼 수 있다고 생각합니다. 내 머리 위로 조금.
Vexille

솔루션은 주로 플랫폼에 따라 다르므로 사용중인 언어 및 / 또는 툴킷도 지정해야합니다.
Raceimaztion

정말? 알고리즘 솔루션이나 의사 코드가 도움이 될 것이라고 생각했습니다. 어쨌든 질문을 편집 할 것입니다.
Vexille

극좌표 (문자 각도에서 최대 각도 및 문자에서 최소 / 최대 거리)로 모양을 정의하십시오. 그런 다음 마우스가 해당 경계 내에있는 경우에만 마우스가있는 위치로 웨이 포인트를 업데이트하십시오. 그것이 extreem을 초과하면 가능한 가장 extreem 값으로 스냅하십시오. 영역 내부를 클릭하면 업데이트를 시작하고 마우스를 놓으면 중지합니다.
ClassicThunder

답변:


8

질문의 영역과 같이 실행 가능한 영역을 세 가지 값으로 정의 할 수 있습니다.

float innerRadius;
float outerRadius;
float maxAngle;

이 값은 플레이어의 위치 일 수도 있고 아닐 수도 있는 중심점을 기준으로합니다 . 작업 영역의 모양은이 지점을 어디에 두느냐에 따라 다릅니다.

여기에 이미지 설명을 입력하십시오

위의 예에서 중심 위치는 플레이어 의 특정 거리 (50 단위라고합시다) 입니다. 이것은 다음과 같이 쉽게 계산할 수 있습니다.

float offset = -50;
Vector2 centerPosition = playerPosition + offset * playerForward;

마커의 위치를 ​​해당 작업 영역으로 제한하려면 먼저 마커를 이동하십시오. 를 평소대로 이십시오. 그런 다음 중심점과 마커 사이 의 거리확인하십시오 .

Vector2 direction = markerPosition - centerPosition;
float distance = direction.Length();
direction.Normalize();
markerPosition = centerPosition + direction * clamp(distance, innerRadius, outerRadius);

드디어, 마커 의 각도 를 지정된 범위로 확인하십시오. 이 코드에는 의사 코드를 사용하겠습니다.

- Find angle between vector C->M and vector playerForward
- If abs(angle) <= maxAngle Then do nothing
- Else If angle > 0 Then rotate M around C by maxAngle-angle
- Else If angle < 0 Then rotate M around C by -maxAngle-angle

다른 점을 중심으로 점을 회전시키는 방법을 살펴보십시오. 삼각법 또는 변환 행렬로 수행 할 수 있습니다.

마커의 크기를 고려하고 보정하기 위해 반경과 각도를 약간 작게 만들 수도 있습니다.

편집 : 두 번째 생각에서 각도를 먼저 확인 한 다음 거리를 확인하면 더 자연스럽게 보일 수 있으므로 두 가지 대안을 모두 시도하십시오!


훌륭한 솔루션! 두 개의 원과 삼각형이 관련된 것을 발견했지만 귀하의 솔루션은 우아하게 단순화합니다. 각도 유효성 검사에 대해 playerForward의 maxAngle (및 다른 -maxAngle)에 서있는 정규화 된 벡터가있는 선을 따라 무언가를 생각했습니다. 각도로. C를 중심으로 M을 회전시키는 솔루션 비용이 저렴하다고 가정합니다. 맞습니까?
Vexille

@Vexille 글쎄, 회전에는 a cossin연산이 포함 되므로 확실하지 않습니다. 그러나이 두 벡터를 계산하려면 순방향 벡터가 변경 될 때만 수행해야하지만 회전해야합니다. 어쨌든 중요하지는 않지만 구현하려는 것을 선택하십시오.
David Gouveia

10

모양이 불규칙하고 문제를 수학적으로 정의 할 수없는 경우 문제를 어떻게 해결할 수 있을지 생각했습니다. 경고 :이 방법은 더러워진 솔루션이며 심장이 약한 것이 아닙니다.

1. 당신의 지역을 가지고 가십시오 :

여기에 이미지 설명을 입력하십시오

그리고 이것을 단색 비트 맵으로 변환합니다 :

여기에 이미지 설명을 입력하십시오 이름을 scale_0

3. 비트 맵을 복제하고 50 %로 축소하십시오.

여기에 이미지 설명을 입력하십시오 이름을 scale_1로 지정하십시오

4. 비트 맵이 4 픽셀보다 작거나 작아 질 때까지 :

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 가늠자 : 2, 3, 4, 5, 6

5. 이제 우리는 다른 해상도의 단색 비트 맵으로 영역을 갖습니다. 여기에 이미지 설명을 입력하십시오

6. 마지막 이미지 (여기서는 "scale_6")를 가져와 모든 픽셀을 반복합니다.

  • 각 픽셀의 좌표를 화면 좌표로 변환합니다. x = Math.pow ( 2, scale_level ); 여기서 scale_level은 "scale_"다음에 추가 한 숫자입니다. 쿼드 트리로 작업하지는 않지만 쿼드 트리 레벨이라고 부를 수도 있습니다. y와 동일하게 수행하십시오.
  • 변환 된 x & y의 픽셀이 검은 색인지 확인하십시오. 그렇지 않은 경우 모양의 일부가 아니며 단지continue 루프의 다음 단계로 넘어 합니다.
  • 픽셀이 이전에 확인 된 픽셀보다 마우스 커서에 더 가까운 지 확인하십시오. 그렇다면, 픽셀의 좌표를 저장하십시오-변환하기 전에 좌표를 사용하십시오.
  • 루프 끝에서이 좌표에 2를 곱하여 x *= 2; y*=2;다음 이미지의 좌표로 변환합니다 (이전 스케일).

7. 이전 이미지 (여기서는 "scale_5")를 가져 오지만 모든 픽셀을 반복하지는 않습니다. x = saved_x에서 시작하고 x와 같은 x = saved_x + 2로 끝납니다. 즉, 지금부터 모든 레벨에 대해 4 픽셀 만 반복합니다! 나머지는 p. 6.

8. 첫 번째 이미지 (가장 큰 = 해상도가 가장 큰 이미지)를 다시 가져 와서 4 픽셀을 반복하면 마우스 커서에 가장 가까운 픽셀이 나타납니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

9. 그러나 여기서는 "M"을 다루고 있습니다. 완전히 맞는 원이 되려면 circle.radius먼저 모양을 픽셀 단위로 축소 (축소)해야합니다 .

단색이 아닌 회색조 이미지를 사용하고 흰색이 아닌 경우 픽셀을 "전체"로 처리하고 정확하게 흰색이면 "빈"으로 처리하는 경우에만이 알고리즘이 작동한다고 생각했습니다. 알고리즘은이 4 개의 픽셀 중 적어도 하나가 흰색이 아닐 때마다 4 픽셀의 모든 그룹을 1 개의 블랙 픽셀로 변경합니다.


2
수학적으로 표현하기 어려운 (불가능하지는 않지만) 도형에 대한 답은 +1입니다.
Cypher

와, 매우 흥미 롭습니다. +1도 : D
Vexille

실제 프로젝트에서 구현했으며 몇 가지 문제가 발생했다고 말해야합니다. 기본적으로 그리드 셀 목록을 작성해야합니다. 여기에서 가장 가까운 그리드 셀을 가져 와서 closest거리 이름을 지정하십시오 . 에서 가장 먼 지점 까지의 거리를 확인하십시오 . 이제 가장 가까운 지점 을 가진 모든 셀을 목록에서 제거 하고 레벨을 더 깊게 제거해야합니다 . : 그래서 그 대신 이런 식으로 뭔가의 i.imgur.com/4UuFo.png 이런 식의 일 : i.imgur.com/dyTT3.pngclosestfurthest_distfurthest_dist
마르쿠스 폰 Broady
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.