211015~18 모작기록-5, 오브젝트의 계단 이동

2021. 10. 19. 01:09·포트폴리오/Castlevania: Aria of Sorrow 모작
/*		오브젝트의 각 지점을 먼저 구해준다.		*/

// 사각형의 왼쪽 상단은 현재 위치 - 피봇*사이즈값.
Vector2	LT = m_Pos - m_Pivot * m_Size;
// 오른쪽 하단은 LT+물체의 크기만큼
Vector2	RB = LT + m_Size;
// 왼쪽 하단은 LT + m_Size의 y 크기만큼
Vector2 LB = LT + Vector2(0.f, m_Size.y);
// 오브젝트 하단 정가운데.
Vector2 MB = (RB + LB) / 2.f;
	

/*		타일맵이 가지고 있는 Line 인스턴스의 숫자를 가져온다.	*/
// Line 클래스의 두 좌표(시작점, 끝점)는 타일맵 상의 타일의 좌상단 좌표에 속하므로
// 추후 알고리즘 개선을 위해 Line 클래스의 X, Y를 인덱스 화 하여 검사할
// Line을 1개로 한정지을 수 있을 것 같다.
int LineCount = TileMap->GetLineCount();

// 라인의 개수만큼 반복을 돌며 검사한다.
for (int Index = 0; Index < LineCount; ++Index)
{
	// 라인의 왼쪽 점과 오른쪽 점을 가져오고 이를 이용하여 어떤 형태의 계단인지 구분한다.
	Vector2 LeftPoint = TileMap->GetLine(Index)->GetLeftPoint();
	Vector2 RightPoint = TileMap->GetLine(Index)->GetRightPoint();
    
	bool IsLeftUp = LeftPoint.y < RightPoint.y ? true : false;
	
    // 계단의 형태에 따라 오브젝트의 좌하단점, 혹은 우측하단점을 검사할 지 결정
	Vector2 Target = IsLeftUp ? LB : RB;
    
	float LineTopY = IsLeftUp ? LeftPoint.y : RightPoint.y;
	float LineBottomY = IsLeftUp ? RightPoint.y : LeftPoint.y;
	
    // 오브젝트의 검사할 점이 계단의 시작점과 끝점이 그리는 사각형 공간 안에 존재할 경우
    // 주요 처리 시작.
    if (LeftPoint.x<= Target.x && Target.x <= RightPoint.x
		&& LineTopY - 0.001f <= Target.y && Target.y <= LineBottomY + 0.001f)
	{
    	// Line의 X, Y를 구하는 공식은 직선의 방정식을 이용하였다.
        // X를 넣으면 Y가, Y를 넣으면 X가 반환된다.
        // OriginY는 검사할 점의 X값을 넣은 경우 반환되는 계단의 Y값이다.
        // MoveY는 Y값에서 좌하단의 높이를 제거하여 현재 오브젝트의 위치에 더해줄 값이다. 
		float	OriginY = TileMap->GetLine(Index)->GetY(Target.x);
		float	MoveY = TileMap->GetLine(Index)->GetY(Target.x) - Target.y;
        
        // 점프 처리, 내가 구현한 게임에는 일반 점프와 특수 점프가 존재하기 때문에
        // 이에 대한 처리가 필요하다.
		if (m_Jump || m_SuperJump)
		{
        	// 점프로 상승한 최대 높이를 갱신한다.
            // 오브젝트가 상승하는 경우에는 갱신되나, 하강하는 경우 갱신되지 않는다.
            // 이 때, 상승하는 경우에는 계단의 높이로 오브젝트의 높이가 고정되지 않기 위해서
            // 나머지 처리를 하지 않도록 break한다.
			if (m_MaxJumpY >= Target.y)
			{
				m_MaxJumpY = Target.y;			
				break;
			}
            // 점프 후 하강하는 경우
			else
			{	
            	// 현재 X좌표 상의 계단 높이 +- 3.0f인 경우
				if (OriginY - 3.0f <= Target.y
					&& Target.y <= OriginY + 3.0f)
				{
                	// 모든 점프 관련 변수 처리
					m_Jump = false;
					m_SuperJump = false;
					m_IsGround = true;
					m_FallTime = 0.f;
                    
                    // 오브젝트의 높이를 계단의 높이로 변경
					m_Pos.y = OriginY;
				}
                
                // 계단 높이 +- 3.0f가 아닌 경우 아직 점프 중인 것이므로 break 
				else
				{
					break;
				}
			}
		}
        
        // 점프 중이 아니더라도 계단에서의 점프 구현을 위해서 m_MaxJumpY를 계속 갱신
		m_MaxJumpY = Target.y;
        
		// 오른쪽 이동인 경우
		if (DirX > 0.f)
		{
			// 좌상-우하단 경사인 경우
			if (IsLeftUp)
			{
            	// 검사할 점보다 경사의 바닥점이 위에 위치한 경우 
                // 바닥이므로 높이를 바닥으로 변경처리
				if (Target.y >= LineBottomY - 5.0f)
				{
					m_Pos.y = LineBottomY;
					m_Velocity.y = 0.f;
				}
                
                // 아닌 경우 바닥쪽으로 움직임 처리
				else
				{
					m_Pos.y += MoveY;
					m_Velocity.y += MoveY;
				}
			}
			// 좌하-우상단 경사인 경우
			else
			{
            	// 검사할 점보다 경사의 상단점이 아래에 위치한 경우
                // 물체의 x,y값을 변경한다.
                // (계단의 끝에서 바닥으로 떨어지는 것을 방지하기 위해 x도 처리해 준다.)
				if (Target.y <= LineTopY + 1.f)
				{
                  m_Pos.x += 5.f;
                  m_Pos.y = RightPoint.y;
                  m_Velocity.y = 0.f;
				}
				else
                {
                    m_Pos.y += MoveY;
                    m_Velocity.y += MoveY;
                }
            }
		}
        // 왼쪽 이동인 경우, 오른쪽 이동의 반대로 처리해준다.
		else if (DirX < 0.f)
		{
			// 좌상-우하단 경사인 경우
			if (IsLeftUp)
          	{
              	if (Target.y <= LineTopY + 1.f)
              	{
                  m_Pos.x -= 5.f;
                  m_Pos.y = LeftPoint.y;
                  m_Velocity.y = 0.f;
              	}
              	else
				{
                  m_Pos.y += MoveY;
                  m_Velocity.y += MoveY;
				}
          	}
			// 좌하-우상단 경사인 경우
            else
            {
				if (Target.y >= LineBottomY - 5.f)
                {
                	m_Pos.y = LineBottomY;
                    m_Velocity.y = 0.f;
				}
                else
                {
					m_Pos.y += MoveY;
                    m_Velocity.y += MoveY;
                }
			}		
		}
        // 어느 방향으로도 이동중이지 않은 경우, 오브젝트의 높이 위치만 계단의 높이로
        // 변경해주면 된다.
		else
		{
			m_Pos.y = OriginY;
			m_Velocity.y = 0.f;
		}
    // 계단을 땅으로 처리하게 하기 위해 땅 위에 있음을 true로 설정
	m_IsGround = true;
}

[소스코드...가 너무 길다.]

 

계단을 나타내는 직선에서의 처리에 4일정도가 소요되었다.

 

구현하면서 생각했던 포인트는

 

    1. 오브젝트의 x값은 키 입력에 따른 변화로 이미 처리되고 있으므로 y값만 변경한다.

    2. 계단 위에서 점프, 점프하여 계단 위로 이동, 이동, 이동하지 않음의 경우가 존재한다.

    3. 오른쪽으로 이동하는 경우와 왼쪽으로 이동하는 경우의 처리가 다르다.

    4. 계단의 끝 지점에서의 처리에 있어서 offset을 두고 처리하고 x값의 위치를 조금 조정해야 끝에서 떨어지지 않는다.

    5. 점프에서 떨어지는 순간을 어떻게 분별할 것인지에 대한 고민

 

다섯가지로 정리할 수 있다.

 

 

부드럽게 오브젝트가 이동할 토대가 마련되었기 때문에

 

앞으로 구현할 타일맵 기반 스테이지에서 계단 구현이 어렵지 않게 되었는데, 

 

두 가지 수정이 필요한 점은

 

    1. 오브젝트의 위치를 기반으로 대각선의 index를 구해오는 것이 아닌

       타일맵에 존재하는 모든 계단을 구해와서 검사한다는 점(시간복잡도가 너무 커진다.)

 

    2. 계단의 끝점 도달 직전, 직전을 나타내는 y값 기준을 하드코딩으로 처리

 

이다.

 

4일이 소모되어 아쉽지만, 꽤 부드럽게 오브젝트가 움직여 만족스럽다.

 

다음 구현 목표는 몬스터 캐릭터이다.

'포트폴리오 > Castlevania: Aria of Sorrow 모작' 카테고리의 다른 글

[내용 정리] 2. 프로젝트 구조 - Manager들  (1) 2025.05.29
[내용 정리] 1. 프로젝트 개요  (0) 2025.05.28
211015 모작기록-4 Line 클래스 기반 충돌체 생성  (0) 2021.10.16
211012 모작기록-3, 맵에 사용될 Line 클래스 작업  (0) 2021.10.13
211010~11 모작기록-2, 끄적끄적  (0) 2021.10.11
'포트폴리오/Castlevania: Aria of Sorrow 모작' 카테고리의 다른 글
  • [내용 정리] 2. 프로젝트 구조 - Manager들
  • [내용 정리] 1. 프로젝트 개요
  • 211015 모작기록-4 Line 클래스 기반 충돌체 생성
  • 211012 모작기록-3, 맵에 사용될 Line 클래스 작업
DevJoo1120
DevJoo1120
  • DevJoo1120
    Jin's Programming
    DevJoo1120
  • 전체
    오늘
    어제
    • 분류 전체보기 (142)
      • 포트폴리오 (7)
        • Castlevania: Aria of Sorrow.. (7)
        • [UE5] KILL Everything (0)
      • C++ (0)
      • 라이브러리 (1)
      • 다이렉트X11 (0)
      • Unreal Engine (11)
        • Unreal Document (1)
        • 이것 저것 (8)
        • UI (1)
      • 자료구조 및 알고리즘 (0)
      • 책 정리 (3)
        • 코딩 테스트 합격자 되기 C++ 편 (10)
      • 코딩 테스트 (32)
        • 프로그래머스 (32)
      • 스파르타 코딩 언리얼 1기 (9)
        • 특강 (0)
        • C++와 Unreal Engine으로 3D .. (2)
      • TIL(Today I Learned) (63)
      • 영어 공부 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    코딩 테스트
    배열
    map
    WINAPI
    스파르타 코딩 클럽
    팀 프로젝트
    Unreal Engine 5
    Til
    C++
    과제
    코딩 테스트 합격자 되기 c++ 편
    Study
    이중 반복문
    정렬
    문자열
    반복문
    코딩테스트
    정리
    책 정리
    프로그래머스
  • hELLO· Designed By정상우.v4.10.5
DevJoo1120
211015~18 모작기록-5, 오브젝트의 계단 이동
상단으로

티스토리툴바