Skip to content
isdnetworks
Go back

같은 것이 두 개 생겨 있었다

Cocos2d-x 로 만든 게임에서 소리 설정을 끄면 효과음은 꺼지는데 배경음이 계속 났다.

Table of contents

Open Table of contents

설정을 읽는 자리를 봤다

소리를 다루는 클래스는 하나만 만들어 쓰도록 돼 있었다. SimpleAudioEngine::sharedEngine() 처럼 정적 함수로 얻어 가는 방식이다.

grep -rn "new SoundManager" 로 찾으니 다른 .cpp 에서 이렇게 쓰고 있었다.

SoundManager* mgr = new SoundManager();
mgr->playBgm("title.mp3");

정해진 함수를 안 쓰고 new 로 만들었다. 그 객체는 설정을 끄는 쪽이 들고 있는 것과 다르다. 끄는 쪽에서 값을 바꿔도 이쪽은 모른다.

못 만들게 막았다

만들 수 있게 열려 있으니 만든 것이었다. 생성자와 복사를 밖에서 못 부르게 막았다.

private:
    SoundManager();
    SoundManager(const SoundManager&);
    SoundManager& operator=(const SoundManager&);

이러면 새로 만드는 코드가 컴파일에서 걸린다. ndk-build 를 돌리니 세 군데가 걸렸다. 문제가 난 자리 말고도 두 곳이 같은 실수를 하고 있었는데, 막기 전에는 그것들이 있는 줄도 몰랐다.

값이 어디에 있는지 봤다

설정 값이 그 객체 안에 있으니 객체가 둘이면 값도 둘이다. 막았어도 이 구조 자체는 남는다. Android 는 ndk-build.so 를 만들고 iOS 는 Xcode 로 빌드하는데, 이 값은 양쪽 다 같은 자리에서 읽어야 한다.

어디서 읽어도 같아야 하는 값은 객체 안이 아니라 저장된 자리에서 읽게 바꿨다.

bool SoundManager::isEnabled() {
    return CCUserDefault::sharedUserDefault()->getBoolForKey("sound_on", true);
}

이러면 객체가 몇 개든 같은 값을 본다.

끄는 것과 멈추는 것

설정 값을 고쳐도 이미 나고 있는 소리는 안 멈춘다. 값을 바꾸는 것과 지금 상태를 바꾸는 것은 다른 일이라 둘 다 해야 껐다는 것이 된다.

CCUserDefault::sharedUserDefault()->setBoolForKey("sound_on", on);
if (!on) {
    SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
    SimpleAudioEngine::sharedEngine()->stopAllEffects();
}

저장은 따로 부를 것이 없었다. 우리가 쓰는 cocos2d-1.0.1-x-0.10.0CCUserDefaultsetBoolForKey 안에서 바로 파일에 쓴다. getXMLFilePath() 가 가리키는 UserDefault.xml 이고 libxml2 의 xmlSaveFile 이 매번 불린다.

그래서 음량 슬라이더에 같은 것을 붙였다가 한 번 걸렸다. 손가락을 끌면 값이 바뀔 때마다 XML 을 다시 쓴다. 슬라이더는 놓을 때만 저장하게 바꿨다.

stopBackgroundMusic() 은 기본값이 bReleaseData = false 라 멈추기만 하고 자료는 들고 있다. 다시 켤 때 빨리 나는 것은 그 덕이다.

껐다 다시 켜면 배경음이 다시 나야 하는지 물어보니 그게 맞다는 답을 받았다. 그러려면 무엇을 틀고 있었는지를 기억해 두는 자리가 필요했다. 없으면 다시 켜도 조용하다.

같은 방식으로 만든 것이 소리 말고도 있었다. 진행 상황을 들고 있는 것과 HTTP 통신을 하는 것이다. 둘 다 막혀 있지 않아서 같이 막았다. 하나만 만드는 구조로 두면 언제 지울지가 애매해져서 앱이 끝날 때 부르는 정리 함수도 뒀다. 안 지워도 앱이 끝나면 사라지지만 정리하는 자리가 있어야 무엇을 들고 있었는지가 드러난다.

정리


Share this post on:

Previous Post
같은 값이 두 곳에 있었다
Next Post
검증이 앱 쪽에 있었다