본문 바로가기

cocos2d-x/pyocopang

cocos2d-x 포코팡 류 게임만들기!! - 12 - 점수 계산

중간에 버그도 하나 잡았고.. 물론 엄청 많겠지만요 ^^; 계속 진행해보겠습니다!
남은 내용은 다음과 같이 진행할 예정입니다.

- 점수 계산 : 코인을 없앨 때 마다 점수 추가
- 화면 전환 : 초기화면이 나오고 화면을 터치하면 게임시작
- 시간 제한 : 60초 시간 제한을 두고, 60초가 지나면 초기화면으로 돌아감

그럼 점수계산부터 시작하겠습니다.


- 12 - 점수 계산


1. 점수 이미지 & 폰트


게임에 숫자나 문자를 표시할 때는 일반 폰트보다는 이미지를 사용한 비트맵 폰트를 주로 사용합니다. 글자에 맞는 이미지를 만들고, 해당 글자에 이미지를 맵핑한 형태로 사용하는데요. 무료 툴인 BMFont, Mac 전용 Glyphs 등 여러 비트맵 폰트 에디터가 있는 것으로 알고 있습니다. 비트맵 폰트 제작 자체도 게임 개발만큼이나 고된 작업이라 저희는 이미 작성해놓은 폰트를 사용하도록 하겠습니다. 다음의 두 개의 파일을 프로젝트의 Resources에 포함시키면, 우리는 코딩을 통해 이 폰트를 자유롭게 사용할 수 있습니다!


font.fnt

font.png

이미지 파일은 따로 'font.png'란 이름으로 저장해서 사용하시기 바랍니다. 점수 표시를 위해 숫자만 필요하기 때문에 다른 문자 이미지는 따로 포함하지 않은 폰트를 사용합니다. 제가 만든 이미지는 아니고요. 구글이나 책 자료에서 받은 것 같은데 정확히 기억은 나지 않습니다. --; 상업적으로 사용하지 말아주세요 ^^;

font.fnt 파일은 font.png의 이미지를 가지고 어떤 글자에 맵핑할 것인지 등의 정보를 가지고 있는 파일입니다. 반드시 font.fnt 와 font.png를 모두 Resources에 추가해주시기 바랍니다.


2. CCLabelBMFont


비트맵 폰트를 위해서 CCLabelBMFont 클래스를 사용합니다. 이 클래스를 통해 font.fnt를 등록하고, 점수가 표시될 위치, 크기 등을 초기화할 수 있습니다. 우리의 메인클래스에 CCLableBMFont 변수를 추가하고, 게임 내에서 점수를 기록할 수 있는 부분의 코드를 작성해보도록 하겠습니다.

/Classes/HelloWorldScene.h

class HelloWorld : public cocos2d::CCLayer
{
private:
    ...
    int _score;
    CCLabelBMFont* _scoreFont;

public:
    ...
    void addGameScore(int deadCoinNum);
};

실제 게임 값을 저장할 _score 변수, 화면에 점수를 출력할 _scoreFont를 선언하고, 죽은 코인에 대해 점수를 계산하게될 addGameScore() 함수도 함께 만들어 보겠습니다.

구현은 간단하게 각 변수를 초기화하고, addGameScore() 함수에서 변경되는 값에 대해 _score, _scoreFont를 설정하고, 최종적으로 addGameScore()를 적절한 곳에 위치시키는 것으로 마무리하겠습니다.


/Classes/HelloWorldScene.cpp

void HelloWorld::createGameScene()
{
    ...
    _scoreFont = CCLabelBMFont::create("0", "font.fnt", _screenSize.width * 0.3f);
    _scoreFont->setAnchorPoint(ccp(1, 0.5));
    _scoreFont->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.95f));
    _scoreFont->setScale(1.5f);
    this->addChild(_scoreFont);

    initGameCoin();
}

createGameScene()에서 CCLabelBMFont 변수를 초기화하겠습니다. create()를 통해 초기값은 "0", 폰트는 당연히 앞서 첨부한 "font.fnt", 그리고 폭을 설정합니다. 자세한 api 내용은 항상 reference를 참고하는 습관을!!

그리고 이어지는 내용은 위치 및 크기 조정과 관련된 것으로 이전에 이미지 추가할 때의 내용과 동일합니다. addChild()까지 하면 font에 대한 준비는 모두 마치게 됩니다.

_score 변수도 동일하게 '0'으로 초기화 하겠습니다.

/Classes/HelloWorldScene.cpp

void HelloWorld::initGameCoin()
{
    ...
    _score = 0;
}

간단합니다!

이제 addGameScore()의 내용을 살펴보겠습니다. 다양하게 점수를 계산할 수 있을텐데, 저는 그냥 귀찮으니까 코인 당 100점 얻는 걸로...

/Classes/HelloWorldScene.cpp

void HelloWorld::addGameScore(int deadCoinNum)
{
    char score[100] = {0,};

    _score += (deadCoinNum * 100);

    sprintf(score, "%i", _score);
    _scoreFont->setString(score);
}

아주 간단하게 (없어진 코인의 수 * 100)을 기존 _score에 누적하고요. 그 값을 문자열로 바꿔서 _scoreFont를 통해 화면에 출력하게 됩니다. 마지막으로 addGameScore() 함수를 코인을 제거하는 부분에 추가하겠습니다.

/Classes/HelloWorldScene.cpp

void HelloWorld::clearSelectCoin()
{
    int index;
    GameCoin* tmpCoin;

    if(_selectCoinCount >= 3) {
        addGameScore(_selectCoinCount);

        for(index = 0; index < _selectCoins->count(); index++) {
            tmpCoin = (GameCoin*)_selectCoins->objectAtIndex(index);
            tmpCoin->setState(GameCoin::DEAD);
            tmpCoin->setVisible(false);
        }
    }
    else {
        for(index = 0; index < _selectCoins->count(); index++) {
            tmpCoin = (GameCoin*)_selectCoins->objectAtIndex(index);
            tmpCoin->setState(GameCoin::LIVE);
        }
    }

    resetSelectMask();
    resetGameInfo();
}

어떻게, 게임이 조금 더 재밌어지셨는지 모르겠습니다. 워낙 별거없이 밋밋한 게임이라 크게 달라진 것은 없습니다만, 색깔 별로 다른 점수를 준다던지, 특정 개수가 넘어가면 보너스가 주어진다던지 등의 추가적인 요소를 구현해보면 또 다른 재미가 생길지도 모르겠습니다.

다음에는 화면 전환을 통해, 초기화면과 실제 게임화면을 구분해보도록 하겠습니다.



이제 얼마남지 않았습니다! 한 달 남짓이면 끝날 줄 알았는데, 반 년이나 질질 끌다니.. :(
어서 빨리 끝내고 다른 걸 하고 싶네요.

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