hyrule 2022. 6. 16. 01:44

http://hyrule.tistory.com/111 

 

*** 공부 방법 ***

1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처

hyrule.tistory.com

 


- 이렇게 캐릭터가 점프했다 도로 떨어지는 상황을 가정해보자.

 

- 그런데 렉이 걸려서 프레임 사이의 시간 간격(DeltaTime)이 1초를 넘었다면

다음 프레임은 이렇게 한번에 충돌 타일을 넘어가버려서 그대로 아래로 추락하는 버그가 발생할 수도 있다.

 

- 이런 상황을 막기 위해서는 '이동량'을 통해서 충돌 계산을 해야 한다.

이런 식으로 말이다.

이렇게 구해놓고 중간에 이동 불가 타일이 있을 경우, 도착 시점의 Bottom 값을 충돌 불가 타일의 위로 올려주면 끝이다.

 


class CTileMap

- 좌표를 통해 IndexX와 IndexY 구하는 메소드는 이미 만들었지만, 해당 메소드는 타일맵을 완전 벗어난 좌표를 -1로 반환해 버린다. 

- 그런데 저 충돌 계산은 타일맵을 벗어날 가능성도 있다.

-> 그러므로 벗어난 곳의 Index까지 계산해주는 메소드 2개를 추가로 만들어준다.

< GetTileOriginIndexX(float PosX) >

< GetTileOriginIndexY(float PosY) >

 

 

- 일단 어떤 타일이 문제인지 쉽게 확인하기 위해 

CTile의 m_Render 변수가 false여도 격자 테두리는 표시해주도록 설정해준다.

-- 여태까지 CTileMap 차원에서 각 CTile의 m_Render 변수를 받아와서 아예 continue를 해 버렸지만,

이렇게 하지 않고 일단 CTile::Render()까지 들어가서 자신의 m_Render이 false면

텍스처만 출력하지 않고 격자 선은 출력하도록 해준다.


class CGameObject

< PostUpdate() >

- 만약 '물리 시뮬레이션(m_PhysicsSimulate)이 켜져 있고' + 'y축 이동량이 아래 방향 또는 0(>=)인 경우(양수)'에만 착지 계산을 한다.

- 소속 CScene으로부터 타일맵의 주소를 미리 받아놓는다.

- Update()에서 구한 m_PrevPos와 m_Pos를 통해서,

이전 프레임과 지금 프레임의 Bottom, Left, Right 값을 구해준다. 총 6개를 구해야 한다.

- 삼항 연산자를 통해 지금 프레임과 이전 프레임 중 누구의 left값이 작은지를 확인해서, 작은 쪽을 Left로 해준다.

- 똑같은 방법으로 Right, Top, Bottom을 구한다.

 

- 위에서 구한 위치 값을 GetTileOriginIndex 메소드에 넣어 인덱스 값을 구한다.

-- 구한 인덱스로, 두 가지 상황에 대한 예외처리를 해주어야 한다.

--1. 검사하는 각 모서리 부분이 타일맵을 넘어가지는 않았는지

이 때는 넘어간 부분을 타일맵의 끝 부분으로 바꿔 준다.

 

 

 

--2. 아예 검사하려는 부분이 바깥으로 나가버린 것은 아닌지

이 때에는 아예 검사를 스킵한다(이 상황이 아닐 경우에만 검사를 진행한다.)

 

 

- 위 두 상황에 대한 예외처리가 되었다면, 순회를 돌면서 검사를 시작한다.

1.  타일의 위부터 아래로 검사한다.

2. 검사하려는 타일 인덱스에 해당하는 타일의 주소를 받아온다.(GetTile())

 

3. 예외처리를 해준다.

-- 타일 주소를 받아오지 못했다면 continue

-- 타일의 m_Pos.y가 검사 이전의 bottom보다 작을 경우

이런 상황. 이 블록은 이미 관통해서 지나간 것이므로 검사를 하지 않는다.(continue)

 

4. 예외처리를 다 통과했으면 충돌검사를 한다.

-- 별거 없이, 그냥 검사한 타일들 중에 ETileOption::Blocked 속성의 타일이 있으면 이 타일 위에 착지해야 된다는 이야기이다.

 

5. 착지해야할 타일이 있을 경우

-- 추락 시간을 0.f로 초기화해준다.

-- 착지한 게임오브젝트의 Bottom 위치를 바닥 타일의 Top으로 바꿔 준다.

-- 착지했으므로 m_Ground 가 true가 된다.

-- 착지했으므로 m_Jump가 false가 된다.

 

6. 검사를 했는데 착지를 하지 않은 경우

-- 근데 m_Ground는 true라면?

--> 이제 막 낙하를 시작했다는 뜻

--- m_FallTime = 0.f로 초기화

--- m_FallStartY = 현재 y위치로 초기화하고

--- m_Ground = false로 변경

 

 


- 작동 테스트를 해보았는데, 문제가 발생했다.

시작하면 캐릭터가 공중부양을 하다가 움직이면 떨어진다.

 

- 이유는 생성자의 초기화 과정에 있었다.

-- Vector2 m_PrevPos는 초기화 과정에서 0, 0으로 초기화된다.

-- 이후, 위치인 m_Pos가 씬의 초기화 과정에서 설정되면, PrevPos = (0, 0) / Pos = (지정한 위치)가 되어,

코드에서 이동한 것으로 인식하는 것이다.


< virtual void Start() >

{ bool m_Start }: 기본값 false

- 모든 세팅이 완료되면, 호출해줄 메소드.

- m_Start값을 true로 바꿔 준다.

- 여기서 세팅이 완료된 이후에 따로 또 설정해주어야 할 변수들을 설정한다.

-- 방금 문제가 발생했던 m_PrevPos를 m_Pos와 같은 값으로 설정해 준다

 

class CScene

< Update(), PostUpdate(), Render() >

- 모든 과정에서 순회를 돌때 m_Start가 true인지 여부를 검사한다.

- 만약 false이면, Start() 메소드를 호출한다.


- 일단 착지 체크만 테스트

착지는 정상작동 확인.

GameFrameworkStepbyStep_78_TileMapGround.zip
11.02MB