해상도와 상관없이 충돌 감지가 작동하도록 화면에서 마우스 위치를 "매핑"하는 것은 좋지 않습니까?


16

기본 해상도가 800x600 인 게임을 생각해보십시오. 충돌 마스크가있는 객체는 800x600 크기의 게임 세계에 배치됩니다. 충돌 마스크는 마우스가 충돌하는시기를 감지 할 수 있습니다.

이제 게임을 1024x768까지 확장 할 수 있습니다 (모든 것을 레이어에 렌더링 한 다음 전체 레이어를 한 번에 확대하여 그래픽을 스케일링한다고 가정). 이 새로운 해상도에서 마우스와 충돌하는 두 가지 옵션이 있습니다.

A.) 월드를 1024x768로 확장하고 그에 따라 모든 오브젝트의 충돌 마스크를 확장합니다.

B.) 마우스 위치를 원래 세계 (800x600)에 "매핑"합니다.

"지도"는 단순히 원래 800x600 세계에 마우스 위치를 조정한다는 의미입니다. 예를 들어, 화면 의 마우스 위치 가 (1024, 768)이면 월드 의 마우스 위치 는 (800, 600)입니다.

이제 분명히, 옵션 B는 필요 방식으로 적은 계산을 아마 기하학적 오류가 적은 경향이 있지만, 나중에 해결하기 위해 지옥이 될 것입니다이 방법으로가는 예상치 못한 결과가있는 것처럼 그것은 또한 나에게 친절 "hackish"의 느낌.

어떤 방법을 사용해야합니까 : A, B 또는 다른 것?


2
Classic Thunder에서 지적한 것처럼 디스플레이 좌표는 월드 좌표 또는 객체 좌표와 같아서는 안됩니다. 일반적으로 변환을 원합니다 (기본적으로 mapping 이라고 말하지만 일반적으로 행렬 수학으로 수행됨).
Dan

답변:


38

일반적으로 (2d 게임의 경우에도) 해상도와 무관 한 별도의 좌표 시스템이 있으며,이를 월드 공간이라고합니다. 이를 통해 임의 해상도로 조정할 수 있습니다.

이를 달성하는 가장 쉬운 방법은 2D 카메라를 사용하는 것입니다. 2D 카메라는 기본적으로 월드 공간 (임의의 단위)에서 화면 공간 (화면의 픽셀)으로의 전환을 정의하는 매트릭스입니다. 이것은 수학을 간단하게 처리합니다.

XNA 2d 카메라 스크롤 에서 아래 섹션을보십시오 -왜 매트릭스 변환을 사용합니까?

좌표계 정의를 쉽게 변환 할 수 있습니다.

화면에서 월드 공간으로 이동하려면 간단히 Vector2.Transform을 사용하십시오. 이것은 일반적으로 객체 선택을 위해 세계에서 마우스의 위치를 ​​얻는 데 사용됩니다.

Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix));

세계에서 화면 공간으로 이동하려면 단순히 반대를 수행하십시오.

Vector2.Transform(mouseLocation, Camera.TransformMatrix);

약간의 학습이 필요한 것 외에 매트릭스를 사용하는 데에는 결점이 없습니다.


실제로 현대 하드웨어는 SSE, NEON 등과 같은 벡터화 아키텍처를 통해 매트릭스 작동을 위해 설계되었습니다. 따라서 현명한 선택입니다. 벡터화되지 않은 방식에 비해 CPU주기를 절약 할 수 있습니다.
엔지니어

1
가벼운 면책 조항 : Microsoft는 XNA를 중단했지만 Monogame은 동일한 API를 사용합니다.
파라

1
물론, 두 좌표계 사이를 변환하기 위해 행렬을 사용하는 것이 현명합니다. 그러나 그 질문에 어떻게 대답합니까? 시스템 A에서 시스템 B로 또는 B에서 A로 맵핑 할 것인지 여부와 결과가있을 경우 그 결과를 결정해야합니다.
mastov

"해상도에 상관없이 충돌 감지가 작동하도록 화면에서 마우스 위치를"매핑 "하는 것은 좋지 않습니까?" 응답한다 ... "는 두 좌표계 사이에서 변환하는 행렬을 사용하는 똑똑"
ClassicThunder

또한 "시스템 A에서 시스템 B로 또는 B에서 A로 매핑하고 그 결과가있을 경우 그 결과를 결정해야합니다." 해상도 및 스케일과 관련이없는 임의의 것을 사용해야합니다. 따라서 A 또는 B가 해상도인지에 따라 C-> A 또는 C-> B입니다. 물론 C를 기본 해상도로 설정하고 거기에서 확장 할 수 있습니다. 포인트는 모든 수학이 동일한 좌표계에서 발생하며 렌더링에 대해서만 스케일됩니다.
ClassicThunder

2

다른 옵션은 다음과 같습니다. 각 입력 마우스 이동 이벤트에서 게임 내 마우스 커서를 마우스 이벤트의 픽셀 수에 해당하는 게임 픽셀 수만큼 이동하십시오. 이것은 실제 마우스 포인터를 중앙에 고정하고 입력 마우스 움직임에 해당하는 양만큼 조준 방향을 회전시키는 3D 게임의 경우 자연스럽게 발생하지만 게임 내 마우스 커서를 나타내는 스프라이트를 이동하여 동일한 방식으로 수행 할 수 있습니다.

당신은 분명히 중심으로 뒤틀림으로 인한 입력 마우스 움직임 이벤트를 무시해야하며, 게임에 모든 입력 지연이있는 경우 무응답이 가장 애매하고 눈에 띄는 측면이 될 것입니다.

부분적으로 사용하는 솔루션은 게임 플레이에서 마우스 위치가 얼마나 중요한지에 달려 있습니다. 이것이 RTS이고 플레이어가 단순히 클릭하여 유닛을 선택하는 경우 A 또는 B 중 더 쉬운 방법으로 갈 수 있습니다. 하향식 슈팅 게임이고 마우스가 캐릭터의 움직임을 직접 제어하는 ​​경우 해상도뿐만 아니라 마우스 움직임과 같은 것에 따라 캐릭터가 움직일 수있는 방법의 가변성을 제한하는보다 심층적 인 솔루션을 원할 것입니다 속도. 마우스가 타겟팅 방향을 제어하는 ​​경우 다른 솔루션 등을 원할 것입니다.


0

ClassicThunder의 답변은 정확하지만 원하는 효과를 얻는 대안 / 간단한 수단의 예를 제공하고자합니다. 빠른 프로토 타이핑, 완전한 기능을 갖춘 라이브러리에 액세스 할 수없는 경우 또는 GPU에 액세스 할 수없는 경우 (예 : 임베디드 시스템)에 대한 간단한 솔루션입니다.

위의 매핑을 수행하려면 다음 함수를 사용할 수 있습니다 (정적 클래스에 정의되어 있다고 가정 Helper).

static float Map(float value, float fromLow, float fromHigh, float toLow, float toHigh)
{
    return ((value - fromLow) / (fromHigh - fromLow) * (toHigh - toLow)) + toLow;
}

(언어를 지정하지 않았지만 C #에 대한 지식이 있으므로 내 예제는 C #입니다.)

그런 다음이 기능을 다음과 같이 사용할 수 있습니다.

float mouseXInWorld = Helper.Map(Mouse.X, 0, Screen.Width - 1, camera.Bounds.X, camera.Bounds.X + camera.Bounds.Width - 1);
float mouseYInWorld = Helper.Map(Mouse.Y, 0, Screen.Height - 1, camera.Bounds.Y, camera.Bounds.Y + camera.Bounds.Height - 1);

어디 camera.Bounds카메라가 볼 수있는 세계 영역 (예 : 화면에 투영되는 영역)을 나타내는 사각형은 ?

Vector또는 Point클래스 가있는 경우 다음 과 같이 맵 함수와 동등한 2D를 작성하여이 프로세스를 더 단순화 할 수 있습니다.

static Vector Map(Vector value, Rectangle fromArea, Rectangle toArea)
{
    Vector result = new Vector();
    result.X = Map(value.X, fromArea.X, fromArea.X + fromArea.Width - 1, toArea.X, toArea.X + toArea.Width - 1);
    result.Y = Map(value.Y, fromArea.Y, fromArea.Y + fromArea.Height - 1, toArea.Y, toArea.Y + toArea.Height - 1);
    return result;
}

매핑 코드를 단순한 하나의 라이너로 만들 수 있습니다.

Vector mousePosInWorld = Map(Mouse.Pos, Screen.Bounds, camera.Bounds);

-1

옵션 (C) : 화면 해상도를 800x600으로 다시 변경하십시오.

이 작업을 수행하지 않더라도 생각 실험으로 고려하십시오. 이 경우 실제 크기에 맞게 그래픽 크기를 조정하는 것은 디스플레이의 책임이며, 800x600 해상도에서 포인터 이벤트를 제공하는 운영 체제의 책임입니다.

모든 것이 그래픽이 비트 맵인지 벡터인지에 달려 있다고 생각합니다. 비트 맵이고 800x600 버퍼로 렌더링하는 경우 마우스를 화면 공간에 다시 매핑하고 실제 화면 해상도를 무시하는 것이 훨씬 쉽습니다. 그러나 이것의 가장 큰 단점은 특히 "8 비트"스타일의 그래픽을 사용하는 경우 업 스케일링이보기 흉하게 보일 수 있다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.