내 플랫 포머 캐릭터가 벽 타일에서 잘리지 않도록하려면 어떻게합니까?


9

현재 지형 타일 (Cave Story에서 빌린 그래픽)이있는 플랫 포머가 있습니다. 게임은 XNA를 사용하여 처음부터 작성되었으므로 기존 엔진 또는 물리 엔진을 사용하지 않습니다.

타일 ​​충돌은 이 답변에 설명 된 것과 거의 똑같이 설명되며 (사각형과 원에 간단한 SAT 사용) 모든 것이 잘 작동합니다.

넘어 지거나 점프하는 동안 플레이어가 벽에 닿는 경우를 제외하고. 이 경우 타일을 잡고 실제로는없는 바닥이나 천장에 닿았다고 생각하기 시작합니다.

캐릭터 잡기 이미지

이 스크린 샷에서 플레이어는 오른쪽으로 이동하고 아래로 떨어지고 있습니다. 따라서 이동 후 충돌이 확인됩니다. 먼저 플레이어 캐릭터가 바닥에서 3 번째 타일과 충돌하여 위쪽으로 밉니다. 두 번째로, 그는 옆에있는 타일과 충돌하는 것을 발견하고 옆으로 밀었습니다. 플레이어 캐릭터가 바닥에 있다고 생각하고 넘어지지 않는 한 최종 결과는 타일에 닿는 동안 타일을 '잡습니다' .

대신 타일을 위에서 아래로 정의하여이 문제를 해결할 수있었습니다. 그러면 매끄럽게 떨어지지 만 그 반대의 경우가 발생하고 벽을 향해 위쪽으로 점프 할 때없는 천장에 부딪칩니다.

플레이어 캐릭터가 벽을 따라 떨어질 수 있도록 어떻게 이것을 해결해야합니까?



@ Byte56 질문은 같지 않지만 대답은 도움이 될 수 있습니다.
doppelgreener

참고 : 지난 몇 주 동안 답변을 실험 할 시간이 거의 없었습니다. @ Byte56 linked라는 질문에 대한 답변으로 세계 충돌 해결을 구현했습니다.이 질문에는 높은 속도로 별도의 버그가 있지만 아직이 질문에 대한 답변을 시도 할 수 없었습니다. 나는 할 수있을 때 시도하고 가능할 때 대답을 받아들이거나 스스로 해결하면 나 자신을 게시 할 것입니다.
doppelgreener 2016 년

답변:


8

가장 간단하고 더 확실한 방법은 숨겨진 가장자리에서 충돌을 확인하지 않는 것입니다. 두 개의 벽 타일이있는 경우 하나는 다른 타일 바로 위에 있으며 위쪽 타일의 아래쪽 가장자리와 아래쪽 타일의 위쪽 가장자리는 플레이어와의 충돌을 확인하지 않아야합니다.

타일 ​​맵을 간단하게 통과하는 동안 어떤 에지가 유효한지 결정할 수 있으며 각 타일 위치에 외부 에지를 플래그로 저장합니다. 충돌 감지 중에 인접한 타일을 확인하여 런타임에이를 수행 할 수도 있습니다.

정사각형이 아닌 타일도보다 쉽고 빠르게 지원할 수있는 동일한 기술의 고급 버전이 있습니다.

아래 기사를 읽는 것이 좋습니다. Cave Story와 같은 현대의 플랫 포머에서 기본 물리 및 충돌 감지에 대한 간단한 소개입니다. 좀 더 구식 인 마리오 느낌을 원한다면 걱정해야 할 몇 가지 트릭이 있지만 대부분 충돌보다는 점프 및 애니메이션 처리와 관련이 있습니다.

http://www.metanetsoftware.com/technique/tutorialA.html http://www.metanetsoftware.com/technique/tutorialB.html


방법 을 명확히 할 수 있습니까충돌하는 동안 일부 모서리를 무시 을 ? 일반적으로 충돌은 두 사각형 (플레이어 경계와 타일 경계)의 교차로 감지됩니다. 당신이 말할 때 없는 개인의 가장자리에 충돌을 확인하기 위해서는 충돌 알고리즘은 직사각형 - 사각형 교차하지만 뭔가 다른 아님을 의미합니까? 귀하의 설명은 의미가 있지만 구현의 모양이 확실하지 않습니다.
David Gouveia

네, 그냥 사각형 선 충돌을하십시오. 선은 항상 축 정렬되므로 단순화됩니다. 상자 상자 검사를 분해 할 수 있습니다.
Sean Middleditch 2016 년

5

여기 내가 할 일을 ...

1) 현재 X, Y 문자 저장

2) X 방향으로 이동

3) 타일 데이터를 가져와 문자의 모든 구석을 확인하고 다음을 수행하여 단색인지 확인하십시오. (X와 Y는 문자 위치입니다)

  • 왼쪽 상단 : 바닥 (X / tileWidth), 바닥 (Y / tileHeight);
  • 오른쪽 상단 : floor ((X + characterWidth) / tileWidth), floor (Y / tileHeight);
  • 왼쪽 아래 : floor (X + / tileWidth), floor ((Y + characterHeight) / tileHeight);
  • 오른쪽 아래 : floor ((X + characterWidth) / tileWidth), floor ((Y + characterHeight) / tileHeight);

...지도 데이터에서 올바른 타일 데이터를 얻기 위해

4) 타일이 단단한 경우 저장된 X를 복원하여 X를 가능한 가장 좋은 위치로 강제해야합니다.

  • 왼쪽으로 이동하는 경우 : X = floor (X / tileWidth) * tileWidth;
  • 오른쪽으로 이동하면 X = ((floor ((X + characterWidth) / tileWidth) + 1) * tileWidth)-characterWidth;

5) Y를 사용하여 2-4 반복

캐릭터가 타일보다 키가 크면 더 많은 타일을 확인해야합니다. 이렇게하려면 tileHeight를 반복하여 characterY 위치에 타일을 추가해야합니다.

int characterBlockHeight = 3;

// check all tiles and intermediate tiles down the character body
for (int y = 0; y < characterBlockHeight - 1; y++) {
    tile = getTile(floor(characterX / tileWidth), floor((characterY + (y * tileHeight)) / tileHeight));
    ... check tile OK....
}

// finally check bottom
tile = getTile(floor(characterX / tileWidth), floor((characterY + characterHeight) / tileHeight);
... check tile OK....

문자가 1 블록보다 넓은 경우 동일하게 수행하지만 characterY, characterHeight, tileHeight 등을 characterX, characterWidth 등으로 바꾸십시오.


2

플레이어의 이동 방법의 일부로 충돌 가능성을 확인하고 플레이어를 다른 물체로 밀어 넣을 수있는 이동을 거부하면 어떻게 되나요? 이것은 플레이어가 블록의 '내부'를 얻지 못하게하므로, 그 아래의 블록의 맨 위에있을 수 없습니다.


1

나는 현재 작업중 인 게임에서 거의 똑같은 문제에 부딪쳤다. 내가 해결 한 방법은 충돌을 테스트 할 때 겹치는 부분의 영역을 저장 한 다음 우선 순위 (가장 큰 영역)를 기준으로 충돌을 처리 한 다음 각 충돌을 두 번 확인하여 이전에 이미 해결되었는지 확인했습니다. 손질.

귀하의 예에서, x 축 충돌 영역은 y 축보다 크므로 먼저 처리됩니다. 그런 다음 y 축 충돌을 처리하기 전에 x 축으로 이동 한 후 더 이상 충돌하지 않는지 확인합니다. :)


1

간단하지만 완벽하지 않은 수정은 플레이어 충돌 상자의 모양을 정사각형이 아닌 것으로 변경하는 것입니다. 모서리를 잘라 팔각형 또는 이와 유사한 것으로 만듭니다. 이렇게하면 벽에있는 타일과 같은 타일과 충돌 할 때 타일에서 미끄러 져 붙 잡히지 않습니다. 코너링을 약간 잡는 것을 여전히 볼 수 있기 때문에 완벽하지는 않지만, 막히지 않고 구현하기가 매우 쉽습니다.


1

이 튜토리얼에서 매우 비슷한 문제가 소개되었습니다 : 게임 개발 소개 . 비디오의 관련 부분은 1:44입니다. 에 있으며 다이어그램 및 코드 스 니펫으로 설명합니다.

통지 14-tilemap.py 는 클리핑 문제를 나타내지 만 15-blocker-sides.py

코드가하는 동안 마지막 자습서 예제가 클립되지 않는 이유를 정확하게 설명 할 수는 없지만 관련이 있다고 생각합니다.

  • 타일 ​​유형에 따라 조건부 충돌 응답 (가장자리가 실제로 활성화되어 있음)
  • 플레이어는 항상 '떨어지고있다'. 플레이어가 타일 위에 놓여있는 것처럼 보이지만 플레이어는 실제로 타일을 반복해서 넘어 가서 다시 맨 위로 밉니다. ( self.resting코드 의 멤버는 플레이어가 점프 할 수 있는지 확인하는 데만 사용됩니다. 그럼에도 불구하고 플레이어는 벽에서 '더블'점프를 할 수 없습니다. 이론적으로는 가능할 수 있습니다)

0

또 다른 방법은 (Byte56에 연결된 질문에 대답했습니다) 충돌 해결이 문자를 빈 자리에 넣는 지 여부를 확인하는 것입니다. 따라서 문제가 발생하면 내부 사각형의 천장에서 충돌을 일으켜 위로 이동합니다. 여전히 다른 타일과 충돌하고 있기 때문에 불법입니다. 대신 여유 공간으로 이동 한 경우 (예 : 상단 타일과의 충돌이 왼쪽으로 이동하는 방식) 이동 한 경우에만 충돌을 발견하면 완료됩니다.

내가 준 대답에는 코드가 있었지만 지나치게 복잡해졌습니다. 해당 시간대 내의 모든 충돌을 추적하고 여유 공간으로 이어지는 충돌 만 취합니다. 그러나 아무도 없다면 캐릭터의 위치를 ​​마지막 위치로 재설정하는 것에 의지했다고 생각하지만 실제로는 추악하고 어쩌면 여유 공간 해상도가 없을 때 원래 마리오와 같은 것을 구현하려고 할 것입니다. 가능합니다. 또한 충돌 해상도 목록을 정렬하고 가장 짧은 거리의 자유 공간으로 만 이동할 수 있습니다 (코드화하지 않았지만 솔루션이 가장 바람직하다고 생각합니다).


0

나는 3D로 3 SAT 만 했으므로 아마도 이것이 맞지 않을 것입니다. 문제를 이해하면 접촉 축과 접촉 할 수 없어서 바닥이있는 것처럼 플레이어가 행동하기 때문일 수 있습니다. 한 가지 해결 방법은 대신 카 랙터에 원 모양을 사용하는 것일 수 있습니다. 그러면 벽을 칠 때 x 축 방향으로 만 접촉 축을 얻게됩니다.

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