본문 바로가기

cocos2d-x/pyocopang

cocos2d-x 포코팡 류 게임만들기!! - 5 - 터치! Touch!

지난 시간까지 제가 생각했던 화면 구성은 모두 마친 것 같습니다. 적을 공격하는 미사일도 없고, 특수 아이템도 없고.. 뭐 그런거 다 없습니다. 아! 점수판과 타임바는 일단 게임을 만들고 나서 나중에 추가할 계획입니다.

이번에는 터치 기능을 추가해보겠습니다. 처음부터 막 여러 개를 없애고 이렇게 하진 못할 것 같고요. 화면을 눌러서 코인을 선택하면 없어지고, 없어진 코인을 선택하면 다시 나타나고! 이정도만 구현해보겠습니다. 

- 5 - 터치! Touch!

터치 동작은 크게 세 가지로 나누어집니다.

- 누르고!
- 움직이고!
- 떼고!!

이렇게 세 가지 동작으로 구분합니다. cocos2d-x 에서는

- 누르고! : ccTouchesBegan
- 움직이고! : ccTouchesMoved
- 떼고!! : ccTouchesEnded

라는 이름의 함수를 통해 각 touch event를 처리하는데요. 그러면 터치관련 각 함수를 추가하고, 코인을 누르면 사라졌다가 다시 누르면 나타나도록 코드를 추가해보겠습니다.

1) 화면을 터치했을 때, 해당 좌표에 코인이 있는지 확인
2) 코인이 있고,
3) 코인이 보이면, 안보이게
4) 코인이 안보이면, 보이게

이대로 만들어보겠습니다.


1. 터치 함수 추가


HelloWorldScene.h, .cpp에 터치 관련 함수를 각각 추가합니다.

Classes/HelloWorldScene.h

    void initGameCoin(void);
    GameCoin* createGameCoin(const CCPoint &pos, int type, int state);

    virtual void ccTouchesBegan(CCSet* touches, CCEvent* event);
    virtual void ccTouchesMoved(CCSet* touches, CCEvent* event);
    virtual void ccTouchesEnded(CCSet* touches, CCEvent* event);
};

Classes/HelloWorldScene.cpp

void HelloWorld::ccTouchesBegan(CCSet* touches, CCEvent* event)
{
    CCTouch* touch = (CCTouch*)( touches->anyObject() );
    CCPoint location = touch->getLocation();
}

void HelloWorld::ccTouchesMoved(CCSet* touches, CCEvent* event)
{
    CCTouch* touch = (CCTouch*)( touches->anyObject() );
    CCPoint location = touch->getLocation();
}

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    CCTouch* touch = (CCTouch*)( touches->anyObject() );
    CCPoint location = touch->getLocation();
}

touch->getLocation()을 통해 실제 터치된 좌표 정보를 받아오겠습니다. 터치관련 event 함수는 Began, Moved, Ended가 있지만, 우선 Began event만으로 원하는 동작을 할 수 있을 것 같습니다.

Classes/HelloWorldScene.cpp

void HelloWorld::ccTouchesBegan(CCSet* touches, CCEvent* event)
{
    CCTouch* touch = (CCTouch*)( touches->anyObject() );
    CCPoint location = touch->getLocation();

    checkPushGameCoin(location);
}

터치한 지점의 좌표를 checkPushGameCoin()에게 넘겨줍니다. 이 함수에서 코인 관련된 동작을 수행하려고 합니다. 


2. 코인 관련 동작


checkPushGameCoin() 함수를 작성합니다. 앞서 말씀드린대로, 터치 좌표값을 받아서 그 위치에 맞는 코인을 선택한 후, 코인의 현재 상태와 반대로 만드는 것이 목표입니다. 코인의 좌표는 지난 시간에 만든 것 처럼, 한 번 정해지면 게임 진행 내내 바뀌지 않기 때문에, 입력받은 좌표값을 이용하여 한 번에 코인의 위치를 찾고 어쩌고 저쩌고 이런 거는 모르겠고요...... 그냥 0번 부터 순서대로 코인을 확인하면서 터치 좌표와 코인이 겹치는지를 확인하겠습니다....--;

Classes/HelloWorldScene.h

    virtual void ccTouchesBegan(CCSet* touches, CCEvent* event);
    virtual void ccTouchesMoved(CCSet* touches, CCEvent* event);
    virtual void ccTouchesEnded(CCSet* touches, CCEvent* event);
    
    int checkPushGameCoin(CCPoint &touchPos);
};

Classes/HelloWorldScene.cpp

int HelloWorld::checkPushGameCoin(CCPoint &touchPos)
{   
    int index;
    GameCoin *tmpCoin;
    
    for (index = 0; index < _gameCoins->count(); index++) {
        tmpCoin = (GameCoin*)_gameCoins->objectAtIndex(index); 
        if (tmpCoin->boundingBox().containsPoint(touchPos) == true) {
            if (tmpCoin->isVisible() == true)
                tmpCoin->setVisible(false);
            else 
                tmpCoin->setVisible(true);
    
            return index;
        }
    }

    return -1;
}

배열의 크기만큼 for문을 돌면서, 각 코인 별로 코인의 위치가 터치의 위치에 해당하는지를 검사합니다. 아주 무식하지만 정확하게는 동작합니다. 나중에 시간이 되면 최적화할 수 있는 방법을 찾아보도록 하겠습니다. 일단은 무식하게라도  동작을 잘 하도록 만들기로 했으니까요.

CCArray->count()로 배열의 크기를 확인하고요. 각 index별로 CCArray->objectAtIndex(index)을 통해 해당 위치의 object - 우리의 경우 GameCoin을 리턴받을 수 있습니다. 리턴받은 GameCoin->boundingBox().containsPoint(pos)로 touch 좌표가 GameCoin image 내에 포함되는지를 확인합니다. 포함이 된다는 것은 코인이 선택되었다는 것을 의미하지요.

코인은 찾았으니, 이제 코인의 상태를 확인합니다. CCSprite->isVisible()을 통해 현재 이미지가 화면 상에 보이게 설정이 되었는지를 확인할 수 있습니다. GameCoin 역시 CCSprite를 상속받았기 때문에 isVisible()을 사용할 수 있습니다. isVisible()값이 true이면 화면에 잘 보이고 있다는 뜻이므로, CCSprite->setVisible(false)로 설정하고, 반대의 경우는 CCSprite->setVisible(true)로 설정합니다.

크게 뭐 구현한 것은 없지만, 빌드를 해서 돌려보면 다음과 같이 잘 돌아가는 것을 확인할 수 있습니다!! 라고 하려고 했는데, 동작을 잘 안하네요. 분명히 코드에는 문제가 없는데요.... 한참 고생해서 찾았습니다. cocos2d-x 한테 나 터치 쓸거다!!라고 알려줬어야 했습니다. 

Classes/HelloWorldScene.cpp

bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }

    createGameAction();
    createGameScene();

    this->setTouchEnabled(true);

    return true;
}

init() 함수에 this->setTouchEnabled(true)를 추가해서 터치 동작을 가능하게 합니다.

다시...

크게 뭐 구현한 것은 없지만, 빌드를 해서 돌려보면 다음과 같이 잘 돌아가는 것을 확인할 수 있습니다!!



다음에는 좀 더 포코팡과 비슷하게 터치동작을 추가해보겠습니다.

... 여기서 끝!