이번에는 시간 경과에 따른 애니메이션을 구현해 보도록 하겠다.
우선, 시간관련 함수를 사용하기 위해서는 #pragma comment(lib, "winmm.lib")을 포함 시켜야 한다.
헤더에 포함 시켜주도록 하자.
timeGetTime() |
컴퓨터가 부팅된 시간으로부터 현재의 시간을 구한다. |
위의 코드들을 간단히 설명하자면. '한번 싸이클을 도는 시간을 측정한다.'
예를들어서
deltaTime = timeGetTime();
PrevTime = timeGetTime();
이 두 변수에는 같은 시간이 들어가 있다.
들어가 있는 시간이 예를들어 5라고 해보자.
deltaTime = timeGetTime() - PrevTime; // 5 = 5 - 5;
PrevTime = timeGetTime(); // 5
deltaTime에는 0이 들어가고
PrevTime에는 5가 들어가게 된다.
while에서 timeGetTime()으로 새롭게 시간을 가져왔지만,
아직 싸이클을 다 돌지 않았기 때문에 위에 선언한 변수의 시간과 같은 시간이 들어온다.
한 번의 싸이클이 끝나고 다음 싸이클이 돌게되면
deltaTime = timeGetTime() - PrevTime; // 0 = 6 - 5;
PrevTime = timeGetTime(); // 6
다음은
deltaTime = timeGetTime() - PrevTime; // 1 = 7 - 6;
PrevTime = timeGetTime(); // 7
. . . . . .
이렇게 게속 돌게 되므로, 일정한 시간을 얻어올수 있게 된다.
Object_Hero.cpp
-----------------------------------------------------------------------------------------------------------------------------------------------------
랜더
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
void Hero::Render()
{
CGPoint pos = this->GetPos();
pos.x -= m_offset.x + m_srcPos.x / 2;
pos.y -= m_srcPos.y;
SelectObject(m_hMemDC, m_hResource);
BitBlt(m_hBackBuffer,
pos.x, pos.y,
m_srcPos.x, m_srcPos.y,
m_hMemDC,
m_srcSize.x + m_srcPos.x * m_nFreame, m_srcSize.y,
SRCCOPY);
} |
cs |
오프셀을 적용시켜준다.
※오프셀이란?
애니메이션
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 |
void Hero::Animation( float _dt )
{
switch(m_iState)
{
case IDLE:
{
m_srcPos = MakePoint(54,144);
m_srcSize = MakePoint(m_iDirection == RIGHT ? 0 : 610, 10);
m_offset = MakePoint(-m_srcPos.x / 2, -m_srcPos.y);
m_dFrameDelay += _dt;
if(m_dFrameDelay > 0.1f)
{
m_dFrameDelay = 0;
m_nFreame++;
if(m_nFreame >= 4) m_nFreame = 0;
}
break;
}
case WALK:
{
m_srcPos = MakePoint(75,143);
m_srcSize = MakePoint(m_iDirection == RIGHT ? 0 : 610, 310);
m_offset = MakePoint(-m_srcPos.x / 2, -m_srcPos.y);
m_dFrameDelay += _dt;
if(m_dFrameDelay > 0.1f)
{
m_dFrameDelay = 0;
m_nFreame++;
if(m_nFreame >= 8) m_nFreame = 0;
}
break;
}
}
} |
cs |
액션
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
void Hero::Action( float _dt )
{
CGPoint pos = GetPos();
m_MoveSpeed = 300.0f * _dt;
m_iState = IDLE;
if(GetAsyncKeyState(VK_RIGHT))
{
pos.x += m_MoveSpeed;
m_iDirection = RIGHT;
m_iState = WALK;
}
if(GetAsyncKeyState(VK_LEFT))
{
pos.x -= m_MoveSpeed;
m_iDirection = LEFT;
m_iState = WALK;
}
if(GetAsyncKeyState(VK_UP)) pos.y -= m_MoveSpeed;
if(GetAsyncKeyState(VK_DOWN)) pos.y += m_MoveSpeed;
this->SetPos(pos.x, pos.y);
} |
cs |
함수들을 차례차례 수정한다.
결과
'API > 이론' 카테고리의 다른 글
이미지 깜박거림 없앰. (0) | 2016.04.29 |
---|---|
캐릭터 뒷배경 검정색 없애기. (0) | 2016.04.29 |
캐릭터 출력하기. (0) | 2016.04.28 |
배경을 클래스화 해서 출력하기. (0) | 2016.04.27 |
여러 이미지 출력을 위한 소스정리 및 파일 나누기 (0) | 2016.04.26 |
이번에는 캐릭터를 출력해 보도록 하자.
캐릭터 이동 정보를 담을 구조체 하나를 선언하자.
좌표는 당연히 x,y축이다.
그 밑에는 x,y를 편하게 사용하기 위해 정의한 함수다.
이 모든것을 header.h파일에 소스를 적어주면 된다.
그리고 저 사진에는 안나왔지만
전처리 헤더파일을 한 번만 참조해주기 위해서
맨 위에 #pragma once를 적어주도록 하자.
header.cpp파일에 함수를 정의해 놓은 것이다.
캐릭터에는 여러가지 상태가 있을것이다.
Direction
바라보는 방향 |
설명 | |
RIGHT |
캐릭터가 오른쪽을 바라본다 | |
LEFT |
캐릭터가 왼쪽을 바라본다. |
State
캐릭터 상태 |
설명 |
IDLE |
아무런 움직임이 없는 상태 |
WALK |
오른쪽 혹은 왼쪽으로 걷는 상태 |
JUMP |
점프를 뛴다.(상승한다.) |
DROP |
점프를 뛴다.(하강한다.) |
ATTACK |
공격모션 |
HIT |
충돌 |
캐릭터의 좌표이동에 대한 정보를 셋팅하는 동시에 가져오기 위하여
멤버 변수로 변수를 하나 만들어주고
멤버 함수도 Set과 Get을 만들어 주었다.
Object에 만들어 곧바로 상속 받게 한다.
변수명 |
설명 |
CGPoint m_srcPos; |
리소스에서의 x,y좌표 |
CGPoint m_srcSize; |
리소스의 사이즈를 나타낸다. |
CGPoint m_offset; |
출력된 리소스의 출력위치 변환을 위한 변수 |
int m_iDirection; |
캐릭터가 바라보는 방향 |
int m_iPrevState; |
캐릭터의 전 상태 |
int m_iState; |
현재 캐릭터의 상태 |
int m_nFreame; |
리소스 프레임 |
float m_dFrameDelay; |
다음 프레임 까지의 경과시간 |
float m_MoveSpeed; |
움직이는 속도. |
void Animation();
void Action();
이 두개의 멤버 함수는
각각 캐릭터의 상태 변화에 따른 애니메이션 적용과
사용자의 키보드의 키값에 따른 변화를 적용할 함수이다.
이것 다음 글에서 구현 하도록 하고 이번 글에서는 캐릭터를 출력만 하겠다.
선언한 변수들을 모조리 초기화 한다.
MakePoint는 헤더에서 구현한 구조체의 x,y값을 정의한 함수이다.
만들어진 리소스를 사용하기 위하여 Hero의 헤더를 포함 시킨다.
그리고 클래스 변수를 전역 변수로 선언한 뒤
비트맵DC 하나 전역변수로 선언해 캐릭터를 가져 올 수 있게 한다.
메세지 루프 구문에서는 캐릭터를 뿌려주는 랜더 함수를 불러오도록 한다.
g_hHero에 LoadBitmap으로 비트맵을 불러온다.
동적 할당한 메모리에 초기화 함수를 불러와 메모리DC와 캐릭터 리소스를 셋팅 및 초기화 해준다.
이 과정이 완료되면 메모리 해제를 잊지 말도록 하자.
결과
'API > 이론' 카테고리의 다른 글
캐릭터 뒷배경 검정색 없애기. (0) | 2016.04.29 |
---|---|
시간 경과에 따른 애니메이션 (0) | 2016.04.29 |
배경을 클래스화 해서 출력하기. (0) | 2016.04.27 |
여러 이미지 출력을 위한 소스정리 및 파일 나누기 (0) | 2016.04.26 |
배경화면 출력하기. (0) | 2016.04.26 |
배경 클래스 헤더 파일을 하나 만들어서 클래스를 하나 선언한다.
클래스의 이름은 BackGround이며 이 클래스는 Object클래스를 부모로 상속받는다.
부모클래스인 Object클래스에서
두 개의 순수 가상함수가 있는데,
Render와 Update다.
순수가상함수를 가볍게 설명 하자면 내용이 없다는 뜻에서 =0이 붙은 함수이다.
이 멤버함수가 포함된 클래스를 상속 받을 시에는 가상 멤버함수로 선언된 함수들을 반드시 재 정의 해줘야 한다.
보시다시피 Render와 Update의 2개의 멤버함수가 있지만 우리가 사용할 것은
Render멤버함수 뿐이다.
Update는 쓰지 않으므로 부모클래스에서 상속 받을 필요는 없지만,
부모 클래스가 다른 클래스도 상속 해 줄수 있으니 별 수 없이 받아오는 것이다.
그런데 별수 없이 받아온 함수가 순수 가상함수 이니 재 정의를 해줘야 하는데
그 방법은 어렵지 않다.
그냥 함수 앞에 블럭( { } )을 붙이고 내용을 채우지 않으면 된다.
Virtual void Update(){}
우리가 사용할 랜더 함수이다.
이 함수가 하는 일은 비트맵을 받아와서 화면에 뿌려주는 일을한다.
m_Resource로 비트맵을 받아와서 m_hMemDC에 뿌려주고, m_hBackBuffer에 복사해준다.
그리고 메인에 WM_PAINT에서 BitBlt을 다시 써서 화면으로 뿌려주면 완료된다.
클래스화된 배경을 사용하려면 메인 함수에 배경 헤더에대한 파일을 #include해주고 배경 클래스 변수를 전역변수로 하나 선언해 준다.
그리고 메세지 루프를 GetMessage에서 PeekMessage로 바꿔줘야 하는데,
깊게는 안들어가고 가볍게 말하자면
GetMessage는 문서용인 반면,
PeekMessage는 게임용이라고 생각하면 된다.
WM_CREATE에서 LoadBitmap으로 불러온 비트맵을
동적할당된 메모리에 Init의 인자로 넘겨준다.
이때 3개의 인자를 넘겨줘야 하는데, 그려질 도화지인 g_hBackBuffer와 그릴 일을 할 g_hMemDC와 그려질 리소스인 g_hBGA를를 넘겨준다.
프로그램 종료시 사용했던 DC들과 동적 메모리를 해제해 준다.
결과
'API > 이론' 카테고리의 다른 글
시간 경과에 따른 애니메이션 (0) | 2016.04.29 |
---|---|
캐릭터 출력하기. (0) | 2016.04.28 |
여러 이미지 출력을 위한 소스정리 및 파일 나누기 (0) | 2016.04.26 |
배경화면 출력하기. (0) | 2016.04.26 |
더블 버퍼링 (0) | 2016.04.25 |