[Cocos2d-x] Day 5 - Scroll Map Box & Player Resource Work

|


 <DAY> 2016.05.22

 < WORK LIST >

 <Class> Object_Hero.cpp & Box_Manager.cpp

 - Scroll Map Box

 - Player Resource Work

 - Player Resource Animation Apply



   1

  Scroll Map Box





   2

  Player Resource Work



IDLE


WALK


ATTACK


DASH


JUMP


DROP


 Work

   New    IDLE

   New   WALK

   New  ATTACK

   New   DASH

   New   JUMP

   New   DROP



   3

 Player Resource Animation Apply



Update에서 플레이어 상태에 따른 애니메이션을 setDisplayFrame으로 바꿔준다.

1
2
3
4
5
6
7
8
9
void Object_Hero::update(float dt)
{
    KeyInput(dt);
    StateChange(dt);
    AnimationSpeed(dt);
 
    this->setDisplayFrame( ChangeAni( m_iState ),(int)m_fFrame % FrameCount( m_iState ) );
    if( m_iState != JUMP && m_iState != DROP && m_iState != START && m_iState != ATTACK    ) m_iState = IDLE;
}
cs


setDisplatFrame( 1. 현 상태, 2. 애니메이션의 프레임 );

1. 현 상태

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char * Object_Hero::ChangeAni( int _State )
{
    switch( _State )
    {
        case START:   return "START";
        case IDLE:     return "IDLE";
        case WALK:     return "WALK";
        case JUMP:     return "JUMP";
        case DROP:     return "DROP";
        case DASH:     return "DASH";
        case ATTACK:  return "ATTACK";
    }
    return "x";
}
cs


2. 애니메이션 프레임

1
2
3
4
5
6
7
8
9
10
11
12
13
void Object_Hero::AnimationSpeed( float dt )
{
    switch( m_iState )
    {
        case START:   m_fFrame += dt * 10;   break;
        case IDLE:     m_fFrame += dt * 5;    break;
        case WALK:     m_fFrame += dt * 20;   break;
        case JUMP:     m_fFrame += dt * 5;    break;
        case DROP:     m_fFrame += dt * 5;    break;
        case DASH:    m_fFrame += dt * 15;   break;
        case ATTACK:  m_fFrame += dt * 10;   break;
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
int Object_Hero::FrameCount( int _State )
{
    switch( _State )
    {
        case START:  return MAXSTART;
        case IDLE:   return MAXIDLE;
        case WALK:   return MAXWALK;
        case JUMP:   return MAXJUMP;
        case DROP:   return MAXDROP;
        case DASH:   return MAXDASH;
        case ATTACK: return MAXATTACK;
    }
    return -1;
}
cs


상태에 따른 키 제어( WALK)

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
if( m_iState != START )
    {
        if(GetAsyncKeyState(VK_RIGHT))
        {
            vec.x = 1;
            if( m_bMoveSpeedIncrease )
            {
                m_iState == ATTACK   && 
                m_iPrevState == WALK || 
                m_iPrevState == ATTACK ?  pos.x += 0 : pos.x += MoveSpeed + 2;
            }
            else
            {
                m_iState == ATTACK   && 
                m_iPrevState == WALK ||
                m_iPrevState == ATTACK ?  pos.x += 0 : pos.x += MoveSpeed;
            }
 
            if( m_iState != JUMP && m_iState != DROP && m_iState != ATTACK )
                m_iState = WALK;
        }
        if(GetAsyncKeyState(VK_LEFT))
        {
            vec.x = -1;
            if( m_bMoveSpeedIncrease )
            {
                m_iState == ATTACK   && 
                m_iPrevState == WALK || 
                m_iPrevState == ATTACK ?  pos.x -= 0 : pos.x -= MoveSpeed + 2;
            }
            else
            {
                m_iState == ATTACK   && 
                m_iPrevState == WALK ||
                m_iPrevState == ATTACK ?  pos.x -= 0 : pos.x -= MoveSpeed;
            }
 
            if( m_iState != JUMP && m_iState != DROP && m_iState != ATTACK )
                m_iState = WALK;
        }
    }
cs


상태에 따른 키 제어( JUMP )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        // 점프
        static bool JumpKeyPress = false;
        if(GetAsyncKeyState('C') && JumpKeyPress == false )
        {
            if( m_iState != DROP && m_iState != JUMP )
            {
                m_iState       = JUMP;
                JumpKeyPress   = true;
                
                if( m_iPrevState == DASH ) 
                {
                    m_fAccelerator       = JUMPPOWER + DASH_JUMP_POWER;
                    m_bMoveSpeedIncrease = TRUE;
                }
                else 
                    m_fAccelerator = JUMPPOWER;
            }
        }
        else if(!GetAsyncKeyState('C')) JumpKeyPress = false;
cs


상태에 따른 키 제어( DASH )

1
2
3
4
5
6
7
        // 대시
        if(GetAsyncKeyState('V') && m_bOneDash == FALSE )
        {
            if( m_iState != DROP && m_iState != JUMP && m_iState != DASH )
                m_iState = DASH;
        }
        else if(!GetAsyncKeyState('V')) m_bOneDash  = FALSE;
cs


상태에 따른 키 제어( ATTACK )

1
2
3
4
5
6
7
8
9
        // 공격
        static bool AttackPress = FALSE;
        if(GetAsyncKeyState('X') && !AttackPress )
        {
            if( m_iState != JUMP && m_iState != DROP )
                m_iState = ATTACK;
            AttackPress = TRUE;
        }
        if(!GetAsyncKeyState('X')) AttackPress = FALSE;
cs



IDLE



WALK



ATTACK


DASH


JUMP & DROP


State Apply

   New    IDLE

   New   WALK

   New  ATTACK

   New   DASH

   New   JUMP

   New   DROP



평 가

 .난이도 : 쉬움

 별   점 :  

 한 마디: 어려운 점은 없었다.

다만, 작업량이 매우 많았기 때문에

번거로운 점은 있었다.

또, 상태가 하나씩 추가 될때마다 

새로 추가된 상태에 대한 전에 작업 

한 상태에따른 제어를 다시 고쳐야

했던 부분이 매우 번거로웠다.





<Progress List> 

 - Key Control

 - Box CollisionCheck

 - Camera Scroll 

 - New Player Resource Work

 New Scroll Map Box                   - <complete>

 New Player OutPut & Animation   <complete>


<Complete List> 

  - Gravity Jump

  - MouseDrag Box Create

  - RayCast

  - File Input And Output

  BackGround Output

  - New Scroll Map Box

  - New Player OutPut & Animation


And

[Cocos2d-x] Day 4 - BackGround & CameraScroll & File Input And Output

|


 <DAY> 2016.05.21

 < WORK LIST >
 <Class> Object_Hero.cpp & Box_Manager.cpp & Object_BackGround.cpp

 - RayCast Revise

 - File Input And Output

 - BackGround Output & Camera Scroll



   1

  RayCast Revise


만들어진 Box중에 제일 작은 Box의 크기를 저장시켜 그 박스의 크기만큼 RayCast에서 이동시킨다.

1
2
3
4
5
Object_Box * Box_Manager::AddBox( CGRect rc )
{
    if( m_fMinSize > rc.size.width  )    m_fMinSize = rc.size.width  - 1;
    if( m_fMinSize > rc.size.height )    m_fMinSize = rc.size.height - 1;
}
cs


fDistance += m_fMinSize바로 이 부분이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Box_Manager.cpp
 
bool Box_Manager::Raycast( CGPoint _start, CGPoint _vec, RaycastHit *_hit, float _Distance )
{
    for( _hit->fDistance = 0; _hit->fDistance < _Distance; _hit->fDistance += m_fMinSize )
    {
        _start.x += _vec.x;
        _start.y += _vec.y;
 
        Object_Box * p = CollisionCheck( _start );
        if( p == NULL ) continue;
 
        _hit->ObTarget = p;
        return true;
    }
    return false;
}
cs


이렇게 한 이유는 플레이어가 어떠한 크기의 Box와 충돌을 하여도 통과하지 않고 충돌을 일으키게 하기 위함이다.




   2

 File Input And Output

Save

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void Box_Manager::SaveBox()
{
    int Count = 0;
 
    FILE * pFile = fopen( "BoxData.txt""wb" );
    if( pFile == NULL ) return;
 
    forint i = 0; i < MAXBOX; i++)
    {
        if( m_pBox[i] == NULL ) continue;
        if( m_pBox[i]->getActive() == false ) continue;
        Count++;
    }
    fwrite( &Count, sizeofint ), 1, pFile );
 
    forint i = 0; i < MAXBOX; i++)
    {
        if( m_pBox[i] == NULL ) continue;
        if( m_pBox[i]->getActive() == false ) continue;
        fwrite( &m_pBox[i]->rc, sizeof( CGRect ), 1, pFile );
    }
    fclose( pFile );
}
 
cs


Load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Box_Manager.cpp
 
void Box_Manager::LoadBox( SceneTower * Scene )
{
    int Count = 0;
 
    FILE *pFile = fopen( "BoxData.txt""rb" );
    if( pFile == NULL ) return;
    fread( &Count, sizeofint ), 1, pFile );
    forint i = 0; i < Count; i++)
    {
        fread( &m_Rrc, sizeof( CGRect ), 1, pFile );
        Scene->addChild( AddBox( m_Rrc ) );
    }
    fclose( pFile );
}
cs


Box의 x,y좌표와 Width, Height크기만 저장하고, 게임을 켤때 좌표와 크기를 불러오면서

다시 AddBox해준다. 





   3

 BackGround Output & Camera Scroll


배경 출력을 위한 class 및 함수 생성.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Object_BackGround.cpp
 
#define   MAXBG        4
 
bool Object_BackGround::init()
{
    if!CCSprite::init() ) return false;
    
    char szFileName[256= {0};
    CCSprite *pBg = new CCSprite;
    forint i = 0; i < MAXBG; i++ )
    {
        sprintf_s( szFileName, "Resource/BackGround/BG_%d.png", i );
        pBg = CCSprite::spriteWithFile( szFileName );
        pBg->setScale( 2 );
        pBg->setAnchorPoint( ccp( 00.5f ) );
        if( i == 1 ) pBg->setPosition( ccp(3915 * i, 2 ) );
        else         pBg->setPosition( ccp(3915 * i, 0 ) );
        
        this->addChild( pBg );
    }
    schedule( schedule_selector( Object_BackGround::update ));
    return true;
}
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
// Scene_Tower.cpp
 
void SceneTower::BackGroundScroll(float dt)
{
    CGPoint HeroPos = m_pHero->getPosition();
    CGPoint MapPos    = this->getPosition();
 
    float fWorldPosX = HeroPos.x + MapPos.x;
    float fWorldPosY = HeroPos.y + MapPos.y;
    float fMaxPosX   = m_Bga->getContentSize().width - CCDirector::sharedDirector()->getWinSize().width;
    float fMaxPosY   = m_Bga->getContentSize().height - CCDirector::sharedDirector()->getWinSize().height;
 
    if( fWorldPosX > MAXWIDTH ) MapPos.x -= 500.* dt;
    if( fWorldPosX < MINWIDTH ) MapPos.x += 500.* dt;
 
    if( MapPos.x > 0 ) MapPos.x = 0;
//    if( MapPos.x < -fMaxPosY ) MapPos.x = -fMaxPosY;
 
    if( fWorldPosY > MAXHEIGHT ) MapPos.y -= 500.* dt;
    if( fWorldPosY < MINHEIGHT ) MapPos.y += 500.* dt;
//    if( MapPos.y > 0 ) MapPos.y = 0;
//    if( MapPos.y < -fMaxPosY ) MapPos.y = -fMaxPosY;
    
    this->setPosition( MapPos );
}
cs

아직 완성된 카메라는 아니다.
추후에 완성 예정.






평 가

 .난이도 : 보통

 별   점 :  

 한 마디: 파일 입출력을 오랜만에 썼

기 때문에 조금 애 먹었다.





<Progress List> 

 - Key Control

 - Box CollisionCheck

 - New File Input And Output - <Complete List>

 - New BackGround Output    <Complete List>

 - New Camera Scroll


<Complete List> 

  - Gravity Jump

  - MouseDrag Box Create

  - New RayCast

  - New File Input And Output

  New BackGround Output


And

[Cocos2d-x] Day 3 - MouseDrag Box Create & RayCast Collision

|


 <DAY> 2016.05.20

 < WORK LIST >
 <Class> Object_Hero.cpp & Box_Manager.cpp

 - MouseDrag Box Create

 - RayCast Collision

 - Gravity Jump Revise



   1

  MouseDrag Box Create


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
// Scene_Tower.cpp
 
bool SceneTower::init()
{
    this->setIsTouchEnabled(true);
}
 
CGPoint SceneTower::getMousePos( NSSet *_pTouches, UIEvent *_pEvent )
{
    CCTouch * pTouch = (CCTouch*)_pTouches->anyObject();
    CGPoint   pos    = pTouch->locationInView(pTouch->view());
    CGPoint   tpos   = CCDirector::sharedDirector()->convertToGL(pos);
 
    return tpos;
}
 
void SceneTower::ccTouchesBegan( NSSet *pTouches, UIEvent *pEvent )
{
    CGPoint pos = getMousePos( pTouches, pEvent );
    startPoint  = pos;
}
 
void SceneTower::ccTouchesMoved(NSSet *pTouches, UIEvent *pEvent)
{
    CGPoint pos = getMousePos( pTouches, pEvent );
}
 
void SceneTower::ccTouchesEnded( NSSet *pTouches, UIEvent *pEvent )
{
    CGPoint pos = getMousePos( pTouches, pEvent );
 
    CGRect rc;
    rc.origin = startPoint;
    rc.size   = CGSizeMake( pos.x - startPoint.x , pos.y - startPoint.y );
 
    this->addChild( ST::call()->BM.AddBox( rc ) );
}
cs






   2

 RayCast Collision



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Box_Manager.cpp
 
bool Box_Manager::Raycast( CGPoint _start, CGPoint _vec, RaycastHit *_hit, float _Distance )
{
    for( _hit->fDistance = 0; _hit->fDistance < _Distance; _hit->fDistance += _Distance * 0.0005f )
    {
        _start.x += _vec.x;
        _start.y += _vec.y;
        
        Object_Box * p = CollisionCheck( _start );
        if( p != NULL )
        {
            _hit->ObTarget = p;
            return true;
        }
    }
    return false;
}
 
cs





   3

 Gravity Jump Revise


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Object_Hero.cpp
 
case DROP:
{
    m_fAccelerator += GRAVITY * dt;
    ST::call()->BM.Raycast( pos, CGPoint(0-3.f), &Hit, m_fAccelerator );
    pos.y          -= Hit.fDistance;
 
    if( Hit.fDistance < 0.1f )
    {
        m_fAccelerator = 0;
        m_iState       = IDLE;
    }
    break;
}
 
cs



평 가

 .난이도 : 보통

 별   점 :  

 한 마디: 충돌과 관련된 RayCast를 만

듬으로써 충돌의 선택지가 넓어지게 

되었다. 




<Progress List> 

 - Key Control

 - Gravity Jump -> <Complete List>

 - Box Create -> MouseDrag Box Create -> <Complete List>

 - Box CollisionCheck


<Complete List> 

  - Gravity Jump

  - MouseDrag Box Create

  - No Data

  - No Data






And
prev | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ··· | 15 | next