cocos2d-x 006 텍스트파일 읽기 / 한글 표시
흑곰입니다.
cocos2d-x 에서 txt 파일 읽기, 그리고 화면에 문자열 띄우는 일이 만만치 않군요. 검색을 제법 많이 했습니다.
일단 화면에 영어와 숫자는 표시되는데 한글이 표시되지 않는 문제가 있었고요.
외부 파일로부터 한글을 읽어들이지 못하는 문제가 있었습니다.
마지막으로, 파일을 읽어들일 수 있는 폴더 경로를 알기 어려웠습니다.
그 과정에서 cocos2d-x 문자열 처리와 관련해 똥똥배님이 쓴 글을 발견했습니다.
무려 5년 전(!)의 포스팅인데요.
행여나 없어질까 싶어 스크린샷 파일로 박제해왔습니다.
(굳이 읽지 않고 skip하셔도 됩니다.)

감격의 눈물을 흘리며(?) 열심히 읽어보았습니다.
요약하자면,
1. cocos2d-x는 애초에 UTF-8 기반입니다. 메모장에서 파일 저장시 인코딩을 UTF-8 로 선택하고 저장하면 한글을 잘 읽습니다.
2. 한글 문자열은 무조건 외부 파일을 읽어들여서 사용할 것. 여러가지로 그게 속편합니다.
이런 내용입니다.
여기에 제가 검색한/알아낸 정보를 덧붙여보자면 다음과 같습니다.
3. 한글을 표시할 때 한글 지원하는 폰트를 사용할 것. 이를 위해 네이버에서 무료 제공하는 나눔고딕을 설치했습니다.
4. 파일을 읽어들일 때 cocos2d-x 에서 제공하는 FileUtils 클래스를 사용해야 합니다.
그럼 텍스트 파일을 읽어 한글 문자열을 화면에 띄우는 것까지 설명해보겠습니다.
작업전 준비사항으로 폰트와 txt 파일이 있습니다.
1. 폰트 준비 : 네이버 검색해서 나눔고딕을 설치하고, C:\cocos2d-x-3.4\projects\basicgame\Resources\fonts 에 폰트 파일들을 넣었습니다. (NanumGothic.ttf / NanumGothicBold.ttf / NanumGothicExtraBold.ttf / NanumGothicLight.ttf)
2. temp.txt 준비 : Resources 폴더 안에 temp.txt 라는걸 만들었습니다. 경로를 찾아내기 위한 파일로, 내용은 아무렇게나 적어두었습니다. (내용이 한 글자 이상 있어야 할겁니다)
3. 1.txt 준비 : Resources 폴더 안에 text 라는 폴더를 만들고, 그 안에 1.txt 를 만들어두었습니다. 내용은 한글과 영어를 적당히 섞어서 3줄 써넣었습니다.
일단 지난번 만들었던 MainScene.cpp 의 init 함수 하단에 txt 파일을 읽고, 글자를 띄우는 코드를 적었습니다.

// txt 파일 읽기
TextManager *textManager = new TextManager();
vector<string> vec = textManager->readFile2Vector(“text/1.txt”);
textManager->logVector(vec);
delete textManager;
// 글자 띄우기
string firstLine = vec[0];
auto label = Label::createWithTTF(firstLine.c_str(), “fonts/NanumGothic.ttf”, 24);
label->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height – label->getContentSize().height));
this->addChild(label, 1);
보시다시피 TextManager 라는 클래스를 만들었는데요.
이걸로 Resources\text\1.txt 를 벡터 형태로 읽어들이고(readFile2Vector), 벡터 내용을 로그로 쓴뒤(logVector),
첫 번째 줄의 내용을 화면에 띄우고 있습니다.
결국 TextManager의 내용이 핵심이 되겠죠.
아직 cpp의 헤더 개념도 모르겠고, 포인터 등 뭐가뭔지 모르겠지만… 나름대로 열심히 만들어보았습니다.

참고로 인크루드한 헤더 및 사용중인 네임스페이스는 다음과 같습니다.
#include “cocos2d.h”
#include <fstream>
#include <vector>
USING_NS_CC; // using namespace cocos2d
using namespace std;
———-
vector<string> TextManager::readFile2Vector(string path) {
// 파일을 읽어들일 절대경로 얻기
// string dirPath = FileUtils::getInstance()->getWritablePath();
string dirPath = FileUtils::getInstance()->fullPathForFilename(“temp.txt”);
dirPath = dirPath.substr(0, dirPath.length() – 8);
log(“dirPath : %s”, dirPath.c_str());
string filePath = dirPath + “” + path;
log(“filePath : %s”, filePath.c_str());
// 리턴용 벡터 선언
vector<string> *result = new vector<string>();
ifstream ifs(filePath);
if (!ifs.is_open()) {
log(“file not found : %s”, filePath.c_str());
return *result;
}
// UTF-8의 앞의 불필요한 3바이트 제거
char head[3];
ifs.read(head, 3);
char buf[1000];
while (!ifs.eof()) {
// 한줄씩 읽어들이기 (1000자까지)
ifs.getline(buf, 1000);
result->push_back((string)buf);
}
return *result;
}
void TextManager::logVector(vector<string> inputVector) {
int vectorSize = inputVector.size();
string ss = “”;
for (int i = 0; i < vectorSize; i++) {
log(“%i : %s”, i, inputVector[i].c_str());
}
}
———-
우선 readFile2Vector 함수는, temp.txt를 이용해 절대 경로를 얻어내고, 글자 뒤쪽 8자리(temp.txt가 8글자입니다)를 잘라내서 Resource 폴더 경로를 얻습니다.
다음으로 1.txt 파일을 한줄씩 읽어 vector에 차곡차곡 쌓고요.
다 읽은 후에는 logVector로 벡터 내용을 로그에 찍어줍니다.
프로그램을 실행하면 아래처럼 나와야 합니다.
