본문 바로가기
Win32 API/기초

Win32 API 기초 : Animation (3)

글: 시플마 2024. 9. 1.

이제 CAnimation 클래스에서 

텍스처 정보를 갖고 있고 render 함수까지

호출해 주고 있기 때문에 CPlayer 클래스에서

텍스처 정보를 갖고 있을 필요가 없고,

그렇기에 텍스처를 CPlayer 클래스에서

그려줄 필요가 없습니다.

 

 

CAnimation 클래스에서는 

 

render 함수를 통해 화면상에 텍스처를 그리고 있습니다.

 

일단 멤버 m_bFinish는 bool형으로 ,

멤버 m_vAnimInfo에 저장되어 있는 프레임들이

모두 재생되고 나면 true가 되어 모든 프레임이

재생되었다는 것을 의미하게 되어 render 함수를

빠져나옵니다.

 

우선은 m_vAnimInfo에 저장되어 있는

프레임들을 한 번만 재생하게 할 겁니다.

 

그래서 m_bFinish가 true가 되면 render를

진행하지 않고 빠져나가게 되죠.

 

 

이후 애니메이션이 가리키고 있는

애니메이터에 접근하고, GetObj 함수를 통해

애니메이터가 가리키고 있는 오브젝트를 얻습니다.

 

GetPos 함수를 통해 오브젝트의

위치 좌푯값을 얻습니다.

 

 

TransparentBlt 함수를 통해 화면상에 

애니메이션이 갖고 있는 멤버 m_vAnimInfo에

저장되어 있는 텍스처를 그릴 겁니다.

 

49 ~ 50번째 줄은 텍스처가 그려질 좌상단의 위치로,

오브젝트의 좌상단 위치와 같습니다.

 

그 다음 51 ~ 52번째 줄은 화면상에 얼마만큼 크기를 

차지하여 그릴 것이냐에 대한 인자입니다.

m_vSliceSize의 x 크기만큼, y 크기만큼

화면상 공간을 사용하겠다고 하면 되겠죠.

 

 

53번째 줄은 텍스처가

갖고 있는 DC를 넘기는 거죠.

 

 

54 ~ 55번째 줄은 텍스처의 어디 부분부터

그릴지에 대한 좌상단 좌푯값을 넘기는 겁니다.

 

 

56 ~ 57번째 줄은 텍스처를 얼마만큼

잘라서 그릴지에 대한 정보입니다.

멤버 m_vAnimInfo의 m_vSliceSize값이

그에 대한 정보이므로 m_vSliceSize을 넘기면 되겠죠.

 

 

마지막으로 텍스처 중 어떤 색을

제외하고 그릴지에 대한 정보입니다.

 

위 코드의 경우 RGB를 각 255로 넣어 주고 있으니 

흰색 부분을 제외하고 화면상에 그리게 되겠죠.

 

 

 

 


 

 

CAnimation 클래스의 render 함수를 통해

 

텍스처를 그리고 나면 다음에는

update 함수를 통해 텍스처를 업데이트해 줍니다.

 

멤버 m_bFinish는 m_vAnimInfo가 보유하고 있는

모든 텍스처를 출력하고 나면 true가 됩니다.

 

true가 되면 바로 return하여 update 함수를 빠져나오죠.

 

 

그게 아니라면 멤버 m_accDT의 값과

DeltaTime을 더하여 다시 m_accDT에 대입합니다.

 

m_accDT값이 m_vAnimInfo가 갖고 있는

텍스처의 m_fDuration값보다 커지면

다음 텍스처를 출력해야겠죠?

 

즉 m_fDuration값이 1인 경우,

m_accDT의 값이 1초가 지나서 1이

넘어가는 순간, 다음 프레임( 텍스처 )를

재생하기 위한 준비를 해줘야 하는 거죠.

 

그래서 m_vAnimInfo의 다음 인덱스에

접근하기 위해 m_iFrm값을 1 증가시킵니다.

 

 

그렇게 계속 증가하여 마지막

텍스처까지 출력하고 나면,

즉 m_vAnimInfo가 갖고 있는 

모든 텍스처의 개수와 m_iFrm의

값이 같거나 더 크면 다시 0번 

텍스처로 돌아가고 m_bFinish에

true를 대입하여 모든 텍스처의

재생이 완료되었음을 나타냅니다.

 

 

단순히 다음 텍스처로 넘어가는

상황에도, 다시 첫 번째 텍스처로 돌아가는

경우에도 m_accDT의 값은 다시 0으로

돌려놔야겠죠?

 

 

위 코드는 순간적으로 렉이 걸리게 되면

DeltaTime이 확 올라갈 겁니다.

 

만약 한 텍스처의 출력 지속 시간이

1초이고 렉이 걸려 DeltaTime이

3초까지 올라간다면 한 프레임에 적어도

두 개 이상의 텍스처가 엄청 빠른 속도로

휙 지나가며 출력되겠죠.

 

이런 상황을 방지하고 싶다면 

밀린 시간만큼 텍스처를 출력하지 않고

건너뜁니다. 그렇게 접근한 m_vAnimInfo의 

인덱스에 존재하는 텍스처를 

출력해 주면 됩니다.

 

 

 

 


 

 

 

 

CAnimation의 update 함수와 render 함수를

호출하는 CAnimator 클래스의 update 함수와

render 함수를 살펴봅시다.

 

먼저 애니메이터가 애니메이션을

가리키고 있는지 체크합니다.

 

애니메이션을 보유하고 있다면

멤버 m_bRepeat가 true인지 체크합니다.

 

m_bRepeat가 true일 때 

가리키고 있는 애니메이션의

모든 애니메이션이 재생되면

다시 처음으로 돌아가 다시 애니메이션을

재생하고, false일 때 모든 애니메이션이

재생되면 더 이상 해당 애니메이션을

재생하지 않습니다.

 

 

m_bRepeat가 true라면 

애니메이션이 Finish 상태인지

체크합니다.

( m_bRepeat가 false라면 최적화로 인해

바로 if 문의 조건을 false로 인식합니다.

&& 연산 뒤의 구문까지는 체크하지 않는 것이죠. )

 

IsFinish 함수는 애니메이션의

멤버 함수로 애니메이션의 멤버 변수인

m_bFinish의 값을 반환하는 함수이죠.

 

즉 22번째 줄과 34번째 줄에 있는

if 문은 m_bRepeat가 true이면서

모든 애니메이션이 재생 완료된 상태라면,

즉 애니메이션이 처음부터 끝까지 계속 반복되게 

설정해 둔 상태에서 마지막 애니메이션까지

재생이 완료된 상태라면,

 

애니메이션의 SetFrame 함수를 통해

0번 프레임으로 세팅해 주고 

m_bFinish를 false로 

m_accDT를 0으로 만들어 줍니다.

 

 

만약 애니메이터의 update와

render 함수가 실행되는 시점에서

m_bRepeat가 false라면

즉, 반복 재생을 하지 않게

할 것이라면 SetFrame 함수는

호출되지 않기 때문에

모든 애니메이션을 쭉 한 번씩만

재생하겠죠.

 

 


 

 

 

여기까지 구현하였다면 

 

CPlayer 클래스의 생성자 부분,

즉 플레이어가 생성될 때 

GetAnimator 함수를 호출하여

애니메이터를 얻고 애니메이터의

Play 함수를 호출하면 하나의 큰 텍스처가

지정한 크기만큼 잘리면서 차례로 출력( 재생 )되겠죠.

 

Play 함수의 두 번째 인자가 true이므로

모든 애니메이션이 재생된 후에 

다시 처음 애니메이션부터 반복 재생될 겁니다.

 


강의 출처 : https://www.youtube.com/watch?v=xuhO2zhtOYI&list=PL4SIC1d_ab-ZLg4TvAO5R4nqlJTyJXsPK&index=38


'Win32 API > 기초' 카테고리의 다른 글

Win32 API 기초 : Camera (1)  (2) 2024.10.04
Win32 API 기초 : Animation (4)  (0) 2024.09.01
Win32 API 기초 : Animation (2)  (0) 2024.08.28
Win32 API 기초 : Animation (1)  (0) 2024.08.19
Win32 API 기초 : Object (1)  (0) 2024.08.18