2014년 12월 9일 화요일

Cocos2d-x에서 게임 라이브 업데이트 기능을 구현하기

요즘 모바일 게임도 PC 게임과 같이 라이브 업데이트 기능을 가지고 있는 경우를 흔히 볼 수 있다. 게임 내에서 사용하는 각종 테이블, 이미지, 사운드, 스크립트 등의 리소스 파일 수정이 필요할 경우 라이브 업데이트 기능을 구현하지 않았다면 이를 수정해서 사용자에게 새로운 빌드를 배포하는데 1주일 정도까지 시간이 걸릴 수 있기 때문에 상용 게임에서 라이브 업데이트 기능은 필수라고 할 수 있다.

Cocos2d-x에는 AssetManager라는 라이브 업데이트에 사용할 수 있는 클래스를 Extension으로 제공한다. 하지만 문서화가 잘 되어있지 않고 라이브 업데이트는 코드가 잘못 동작했을 경우 발생할 수 있는 부작용이 크기 때문에 AssetManager를 분석하여 사용하는 대신에 이해하기 쉽게 간단히 라이브 업데이트 기능을 구현해 보았다.(압축 해제 루틴은 AssetManager 클래스를 그대로 참조하였다.) https://github.com/lekdw/cocos2dx-live-update에 작성한 코드를 공개하였으니 참고하기 바란다.

프로젝트에서 cocos2d 폴더와 Android, iOS 프로젝트 폴더가 생략되었으므로 Cocos2d-x 프로젝트에서 복사하여 사용하도록 한다. Update 폴더에 테스트로 만들어 놓은 업데이트 파일과 버전 파일을 라이브 업데이트를 위한 Http 서버에 복사해 놓은 후 AssetPanel.cpp의 VERSION_FILE_URL에 버전 파일 위치로 변경하고 Win32 프로젝트를 빌드하여 실행하면 다음과 같이 새로운 버전 업데이트 파일을 다운로드하여 압축을 해제하는 것을 확인할 수 있다.



다운로드한 업데이트 파일이 저장되고 압축이 해제되는 위치는 코드 상에서 FileUtils::getInstance()->getWritablePath() + "asset/"이고 번들의 Resources 디렉토리보다 파일 찾기 우선순위가 높기 설정되어 있기 때문에 업데이트된 파일과 버전 파일을 asset 디렉토리에서 읽어들이게 된다. 파일 찾기 우선순위는 AppDelegate.cpp에서 아래과 같은 코드로 변경된다.

AppDelegate.cpp
bool AppDelegate::applicationDidFinishLaunching() {
  (생략)

  // 캐쉬 디렉토리에 에셋 디렉토리가 없으면 생성한다.
  std::string assetPath = FileUtils::getInstance()->getWritablePath() + "asset/";

  if (!FileUtils::getInstance()->isDirectoryExist(assetPath))
    FileUtils::getInstance()->createDirectory(assetPath);

  // 캐쉬 디렉토리의 에셋 디렉토리에서 먼저 리소스 파일을 찾을 수 있도록 설정한다.
  // 요청하는 리소스 파일이 캐쉬 디렉토리의 에셋 디렉토리에 없을 경우는 번들 리소스 디렉토리에서 찾는다.
  std::vector searchPath;
  searchPath.push_back(assetPath);

  for (std::string path : FileUtils::getInstance()->getSearchPaths())
    searchPath.push_back(path);

  FileUtils::getInstance()->setSearchPaths(searchPath);

  (생략)
}

구현된 라이브 업데이트 기능의 실행 플로우를 그려보면 아래와 같다.


파일 다운로드는 Cocos2d-x의 network::HttpClient 클래스를 사용하는데 이 클래스 구현은 파일 다운로드 진행 상황을 알 수가 없다.다운로드 진행 상황을 Polling 방식으로 알 수 있도록 network::HttpClient 클래스가 수정되어 적용되었다.

프로세스 항목 중에서 파일 다운로드와 압축 해제 과정은 별도의 Thread에서 처리되므로 Cocos2d-x Thread가 Block되지 않도록 AssetPanel.cpp에 구현되어있다. 모든 처리가 완료된 후 프로그램을 다시 실행하면 다음과 같이 라이브 업데이트가 적용된 것을 확인할 수 있으며 Android, iOS 모두 동일하게 동작한다.





댓글 없음:

댓글 쓰기