Skip to content
isdnetworks
Go back

같은 값이 두 곳에 있었다

Cocos2d-x 로 만든 게임에서 아이템 개수가 화면과 실제가 달랐다. 화면에는 3개인데 쓰면 2개만 쓰였다.

Table of contents

Open Table of contents

두 곳에 있었다

Player 쪽에 실제 개수가 있고 HUDLayer 쪽에 그리는 개수가 따로 있었다. 아이템을 먹으면 둘 다 고쳐야 한다.

player->addPotion(1);
hud->setPotion(hud->getPotion() + 1);

두 줄을 같이 써야 하니 한쪽만 쓰는 자리가 생긴다. 실제로 보상으로 받는 경로에서 화면 쪽을 안 고치고 있었다.

화면이 읽어 가게 했다

값을 두 곳에 두는 대신 HUD 가 플레이어 쪽에서 읽어 가게 했다. scheduleUpdate() 를 켜면 update(ccTime dt) 가 매 프레임 불린다. 거기서 읽되 바뀌었을 때만 다시 그린다.

int n = m_player->getPotionCount();
if (n != m_lastDrawn) {
    m_label->setString(...);
    m_lastDrawn = n;
}

마지막으로 그린 값을 들고 있지만 그건 다시 그릴지 정하는 용도일 뿐이다. 값 자체는 한 곳에만 있다.

바뀔 때만 그리는 데는 다른 이유도 있었다. CCLabelTTF::setString 을 열어 보니 부를 때마다 CCTexture2D 를 새로 만들어 글자를 그린다. 매 프레임 부르면 초당 예순 장을 만드는 셈이다.

자주 바뀌는 숫자는 CCLabelBMFont 로 바꿨다. 이쪽은 아틀라스에서 글자 스프라이트를 꺼내 쓰기만 한다. 텍스처를 새로 만들지 않는다.

바뀔 때 알려 주는 방식도 있었다. Player 에 콜백을 걸어 두고 값이 바뀔 때 부르는 것이다. 읽어 가는 쪽은 매 프레임 확인하는 비용이 든다. 대신 알려 주는 것을 빠뜨릴 자리가 없다. 알려 주는 쪽은 확인이 없는 대신 한 군데를 빠뜨리면 화면이 안 바뀐다. 화면 요소가 몇 개 안 돼서 빠뜨릴 자리가 없는 쪽으로 했다.

저장과 서버 값

앱을 껐다 켜니 개수가 또 달랐다. 개수를 더하는 함수가 메모리만 고치고 CCUserDefault 쓰기는 다른 자리에서 따로 하고 있었다. 값을 바꾸는 자리에서 같이 저장하게 했다. 따로 두면 또 한쪽만 하게 된다.

그러니 한 프레임에 여러 번 바뀔 때 저장도 여러 번 일어났다. CCUserDefault 는 값을 넣을 때마다 UserDefault.xml 을 다시 쓴다. 바뀌었다는 표시만 해 두고 프레임 끝에 한 번 쓰게 했다. 값은 여전히 한 곳에 있다.

서버에서 받은 값과도 갈렸다. HTTP 응답이 늦게 오면 그 사이에 먹은 아이템이 사라진다. 받은 값은 요청을 보낸 시점의 값이기 때문이다. 어느 시점의 값인지를 같이 받아서 그 뒤에 바뀐 것이 있으면 안 덮게 했다.

무엇이 원본인지 적었다

같은 값이 여러 자리에 보이는 것 자체는 없앨 수 없었다. HUDLayer 에도 있고 UserDefault.xml 에도 있고 MySQL 에도 있다.

무엇이 원본인지를 코드에 적었다.

/* 아이템 개수의 원본은 여기다.
   화면은 읽어 가고, 저장은 이 값을 따라간다.
   다른 곳에서 따로 세지 않는다. */
int m_potionCount;

적어 두니 화면 쪽에 값을 하나 더 두려는 생각을 안 하게 됐다.

정리


Share this post on:

Previous Post
안 보이는 문자 하나가 스크립트를 막았다
Next Post
같은 것이 두 개 생겨 있었다