본문 바로가기

cocos2d-x/pyocopang

cocos2d-x 포코팡 류 게임만들기!! - 10 - 코인 애니메이션

이번에는 코인이 떨어지는 동작을 만들어보겠습니다. 지난 시간에 코인의 이전 위치와 새 위치를 확인해서 변경하는 내용까지 살펴보았는데요. 단순히 위치를 변경하는 것이 아니라, 기존 위치에서 새 위치로 움직이는 액션을 추가하면 코인이 아래로 떨어지는 형태의 애니메이션을 구현할 수 있습니다.


- 10 - 코인 애니메이션

1. MOVE state


기존의 코인 state는 LIVE, DEAD, SELECT로 구분되었습니다. 코인이 '움직이는 동작' 역시 하나의 상태이므로 움직이는 중간에 다른 동작과 혼선이 없도록 MOVE state를 추가하도록 하겠습니다.

/Classes/GameCoin.h

class GameCoin : public CCSprite
{
private:

public:
    enum gameState {
        LIVE,
        DEAD,
        SELECT,
        MOVE,
    };  
    ...
};

코인이 바닥 쪽으로 움직이는 동안에는 이 상태를 유지할 수 있도록 설정하겠습니다. 움직임이 모두 끝나면 다시 LIVE 상태로 변경하여 사용자가 자유롭게 선택할 수 있게 하고요.


2. 움직이는 액션 추가


다음으로 각 코인에 대해 밑으로 떨어지는 액션을 추가하도록 하겠습니다. 필요한 함수를 다음과 같이 선언하고 구현하겠습니다.

/Classes/HelloWorldScene.h

class HelloWorld : public cocos2d::CCLayer
{
private:
    ...
public:
    ...
    void moveCoin(GameCoin* coin, CCPoint& pos);
    void coinMoveDone(CCNode* pSender);
};

moveCoin()에서 코인에 대한 액션을 추가하고, coinMoveDone()에서는 움직이는 동작이 끝나면, 코인의 상태를 LIVE로 변경하겠습니다. moveCoin() 함수부터 확인하겠습니다.

/Classes/HelloWorldScene.cpp

void HelloWorld::moveCoin(GameCoin* coin, CCPoint& pos)
{
    float duration = 0.0f;
    float coinSpeed = 1000.0f;
    CCPoint prevPos = coin->getPosition();
    coin->setState(GameCoin::MOVE);
    coin->stopAllActions();

    duration = prevPos.getDistance(pos) / coinSpeed;

    CCFiniteTimeAction* movePos = CCSequence::create(
            CCMoveTo::create(duration, pos),
            CCCallFuncN::create(this, callfuncN_selector(HelloWorld::coinMoveDone)), NULL);

    coin->runAction(movePos);
}

액션을 사용하는 방법은 이전에 이미 여러 번 다루었으므로 자세한 내용은 생략하고요. 여기서 사용하는 액션에 대해서만 설명하겠습니다. 일단, setState(GameCoin::MOVE)를 통해 앞서 추가한 MOVE 상태로 현재 코인의 상태를 변경하면서 시작합니다.

여기서 사용할 액션은 CCMoveTo 인데요. 이름에서 알 수 있는 것처럼 특정 위치까지 이동하는 액션입니다. 액션을 만드는 부분을 보겠습니다.

CCMoveTo::create(duration, pos) : pos 위치까지 duration 동안 이동합니다. 즉, duration이 10초라면, 현재 위치부터 pos 위치까지 이동하는데 10초가 걸린다는 의미이지요.

( 시간 = 거리 / 속력 )

이기 때문에 우리가 사용하는 duration 또한 prevPos.getDistance(pos) / coinSpeed 로 결정합니다. 거리는 변경하지 못하므로 coinSpeed 값을 변경해서 떨어지는 속력이 어떻게 달라지는지 확인할 수 있습니다. 

이렇게 움직이는 액션이 끝나면 coinMoveDone() 함수를 호출합니다. 이 함수에서는 다음과 같이 코인의 상태를 다시 LIVE로 변경합니다.

/Classes/HelloWorldScene.cpp

void HelloWorld::coinMoveDone(CCNode* pSender)
{
    GameCoin* coin = (GameCoin*)pSender;

    coin->stopAllActions();
    coin->setState(GameCoin::LIVE);
}

이제 액션은 모두 만들었으니 실제로 적용해보도록 하겠습니다. changeCoin()에서 코인의 위치를 변경했었는데, 여기서 코인의 위치를 결정하는대신 코인에 액션을 추가하도록 하겠습니다.

/Classes/HelloWorldScene.cpp

void HelloWorld::changeCoin(int index1, int index2)
{
    CCPoint tmpPos;
    GameCoin* tmpCoin1 = (GameCoin*)_gameCoins->objectAtIndex(index1);
    GameCoin* tmpCoin2 = (GameCoin*)_gameCoins->objectAtIndex(index2);

    tmpPos = tmpCoin2->getPosition();
    tmpCoin2->setPosition(tmpCoin1->getPosition());

    moveCoin(tmpCoin1, tmpPos);

    _gameCoins->exchangeObjectAtIndex(index1, index2);
}

이전과 달라진 내용을 보면 tmpCoin1의 위치를 추가하던 것에서 moveCoin()으로 액션을 추가한 것을 확인할 수 있습니다. tmpCoin2의 경우 어차피 setVisible(false)로 보이지 않는 상태가 되었으므로 따로 액션을 추가할 필요는 없을 것 같습니다.

이제 확인을 해보면!! 원하는 대로 잘 돌아가는군요! 떨어지는 속도는 중간점검에 올렸던 동영상을 확인해보시면 될 것 같습니다.

2014/06/18 - [cocos2d-x/pyocopang] - [중간점검] cocos2d-x 포코팡 류 게임만들기!! 최종 게임영상 및 계획



너무 이 프로젝트에 오래 매달려있는 것 같아서 요새 속도 좀 내고 있습니다. 이제 거의 다 왔는데요. 서두르다가 내용이 부실해지는 것은 아닌지 모르겠습니다. 방문자 수를 보면 거의 오시는 분도 없지만 ^^; 개인적인 기록을 남기는 의미에서라도 마지막까지 열심히!!

다음에는 사라진 코인 위치에 새로운 코인을 생성하도록 하겠습니다.

읽어주셔서 감사합니다! 끝.