캐릭터 점프

|

현재 캐릭터의 좌표는 x,y로 관리하고 있다.

점프를 하기 위해서는 z축이 필요하다.

하지만 없으므로 가상 z축을 만들기로 하겠다.

물론 가상 z축은 실제로는 y축이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Hero : public Object{
private:
    HDC hDC;
    CGPoint m_srcPos;
    CGPoint m_srcSize;
    CGPoint m_offset;
    int m_iDirection;
    int m_iPrevState;
    int m_iState;
    int m_nFreame;
    float m_dFrameDelay;
    float m_MoveSpeed;
    float m_JumpPower;
    float m_fz;
public:
    virtual void Init( HBITMAP _m_hResource );
    virtual void Render();
    virtual void Update( float _dt );
 
    void Animation( float _dt );
    void Action( float _dt );
 
    static Hero *Create( HBITMAP _Hero );
};
cs

히어로 클래스의 맴버 변수를 2가지 추가 하도록 하겠다

하나는 가상z축과 또 하나는 점프하는 파워다.

변수명 

설명 

 m_JumpPower

점프 하는 힘. 

 m_fz

 가상 z축

그리고 헤더에 2가지를 정의하겠다.

1
2
#define JUMP_POWER    700
#define GRAVITY        1500
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
void Hero::Render()
{
    HDC m = ST::Call()->g_hMemDC;
    HDC b = ST::Call()->g_hBackBuffer;
 
    CGPoint pos = this->GetPos();
 
    pos.x -= m_offset.x + m_srcPos.x / 2;
    pos.y -= m_srcPos.y + m_fz;
 
    SelectObject(m, m_hResource);
 
    BitBlt(b, 
            pos.x, pos.y,
            m_srcPos.x, m_srcPos.y,
            m,
            m_srcSize.x + m_srcPos.x * m_nFreame, m_srcSize.y + m_srcPos.y,
            SRCAND);
 
    BitBlt(b, 
            pos.x, pos.y,
            m_srcPos.x, m_srcPos.y,
            m,
            m_srcSize.x + m_srcPos.x * m_nFreame, m_srcSize.y,
            SRCPAINT);
}
cs

가상 z축이지만 실제로는 y축을 이용해야 하기 때문에

점프 키를 누르면 y값이 +됐다가 다시 -되야 한다.

그렇기 때문에 pos.y에 m_fz을 + 해준다. (pos.y -= m_srcPos.y + m_fz;)

 

 

이제 상태에 따른 애니메이션을 주도록 하겠다.

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
void Hero::Animation( float _dt )
{
    if(m_iPrevState != m_iState)
    {
        m_iPrevState  = m_iState;
        m_dFrameDelay = 0;
        m_nFreame     = 0;
    }
 
    switch(m_iState)
    {
    case IDLE:
        {
            m_srcPos        =    MakePoint(54,144);
            m_srcSize        =    MakePoint(m_iDirection == RIGHT ? 0 : 61010);
            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 : 610310);
            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;
        }
    case JUMP:
        {
            m_srcPos        =    MakePoint(85,135);
            m_srcSize       =    MakePoint(m_iDirection == RIGHT ? 0 : 610610);
            m_offset        =    MakePoint(-m_srcPos.x / 2-m_srcPos.y);
 
            m_dFrameDelay += _dt;
            if(m_dFrameDelay < 0.1f)
            {
                m_JumpPower = JUMP_POWER;
                m_nFreame = 0;
                break;
            }
            
            m_fz += m_JumpPower * _dt;
            m_JumpPower -= GRAVITY * _dt;
 
            if(m_dFrameDelay > 0.1f) m_nFreame = 1;
            if(m_dFrameDelay > 0.2f) m_nFreame = 2;
            if(m_dFrameDelay > 0.3f) m_dFrameDelay = 0.1f;
 
            if(m_JumpPower <= 0)
            {
                m_iState = DROP;
                m_JumpPower = 0;
            }
            break;
        }
    case DROP:
        {
            m_srcPos        =    MakePoint(85,135);
            m_srcSize       =    MakePoint(m_iDirection == RIGHT ? 0 : 610610);
            m_offset        =    MakePoint(-m_srcPos.x / 2-m_srcPos.y);
 
            
            m_fz -= m_JumpPower * _dt;
            m_JumpPower += GRAVITY * _dt;
            m_dFrameDelay += _dt;
 
            if(m_fz <= 0)
            {
                m_fz = 0;
                if(m_dFrameDelay > 0.2f) m_nFreame = 5;
                if(m_dFrameDelay > 0.3f) m_nFreame = 6;
                if(m_dFrameDelay > 0.4f) m_iState = IDLE;
            }
            else
            {
                m_nFreame = 3;
                if(m_dFrameDelay > 0.1f) m_nFreame = 4;
            }
            break;
        }
    }
}
cs

 

점프 상태로 들어왔을 때

1
2
3
4
5
6
7
m_dFrameDelay += _dt;
if(m_dFrameDelay < 0.1f)
{
    m_JumpPower = JUMP_POWER;
    m_nFreame = 0;
    break;
}
cs

딜레이 시간이 0.1보다 작으면

점프 파워를 700으로 대입해주고 프레임을 0으로 대입시켜준다.

딜레이 시간때문에 이 if문은 다음부터는 실행되지 않게 된다.

 

1
2
m_fz += m_JumpPower * _dt;
m_JumpPower -= GRAVITY * _dt;
cs

z값이 = 점프파워(700) * 시간(0.1)

점프파워 = 중력(1500) * 시간(0.1)

시간이 지남에 따라 점프파워는 점점 감소하게 된다.

 

1
2
3
if(m_dFrameDelay > 0.1f) m_nFreame = 1;
if(m_dFrameDelay > 0.2f) m_nFreame = 2;
if(m_dFrameDelay > 0.3f) m_dFrameDelay = 0.1f;
cs

처음 점프를 뛰었을때에 프레임이라 생각하면 된다.

 

1
2
3
4
5
if(m_JumpPower <= 0)
{
    m_iState = DROP;
    m_JumpPower = 0;
}
cs

점프 파워가 점점 감소하므로 결국 0보다 작아진다.

0보다 작아지면 점프의 상태를 DROP로 바꿔주어 떨어주는 모션을 준다.

DROP같은 경우는 점프와 비슷하므로 자세한 설명은 생략하겠다.

 

 

키를 눌렀을때 점프를 해야되는데 그 키 값을 정해주도록 하자.

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::Action( float _dt )
{
    CGPoint pos = GetPos();
    m_MoveSpeed = 300.0f * _dt;
 
    if( m_iState != JUMP && m_iState != DROP )
        m_iState = IDLE;
 
    if(GetAsyncKeyState(VK_RIGHT))
    {
        pos.x += m_MoveSpeed;
        m_iDirection = RIGHT;
        if( m_iState != JUMP && m_iState != DROP ) m_iState = WALK;
    }
    if(GetAsyncKeyState(VK_LEFT))
    {
        pos.x -= m_MoveSpeed;
        m_iDirection = LEFT;
        if( m_iState != JUMP && m_iState != DROP ) m_iState = WALK;
    }
    if(GetAsyncKeyState(VK_UP))
    {
        pos.y -= m_MoveSpeed;
        if( m_iState != JUMP && m_iState != DROP ) m_iState = WALK;
    }
    if(GetAsyncKeyState(VK_DOWN))
    {
        pos.y += m_MoveSpeed;
        if( m_iState != JUMP && m_iState != DROP ) m_iState = WALK;
    }
    if(GetAsyncKeyState('C'))
    {
        if(m_iState != DROP) m_iState = JUMP;
    }
    this->SetPos(pos.x, pos.y);
}
cs

 

 

1
if( m_iState != JUMP && m_iState != DROP )
cs

모든 키값에 if문 추가.

이 if문을 추가 시켜주면 점프중이나 드롭중일때 상태가 변하지 않으므로

2단 이상의 점프가 불가능 해진다.

 

1
2
3
4
if(GetAsyncKeyState('C'))
{
    if(m_iState != DROP) m_iState = JUMP;
}
cs

점프 키는 C가 되시겠다.

 

결과

 

 

 

And