본문 바로가기
cocos2d-x

[cocos2d-x]#4 UI에 대해 알아보자.

by chunma1126 2025. 1. 8.

 

 

유니티엔진에서도 UGUI라고 UI프레임 워크를 제공해준다.Cocos2dx도 마찬가지로 기본적인 Button,Image,Text등의 UI프레임 워크를 제공한다.

 

Label

Cocos2dx에서는 확장자가 다양하여도 손 쉽게 Label을 만들수 있다.

 

BMFont의 Label을 만드는법은 다음과 같다.

auto myLabel = Label::createWithBMFont("bitmapRed.fnt", "My Text");

 

BMFont는 게임에서 텍스트를 표시하기 위해 하나의 .png 파일과 .fnt 파일만 있으면 된다.

png 파일은 사용할 모든 글자를 포함한 이미지이고, .fnt 파일은 각 글자의 위치, 크기, 간격등의  정보를 담고 있다.

 

특정 텍스트를 출력할 때, 필요한 글자를 .png에서 찾아와 조합하는 방식으로 렌더링된다.

하지만 확장성이 떨어진다는 단점이 있다.

 

 

TTF의 Label을 만드는법은 다음과 같다.

auto myLabel = Label::createWithTTF("Your Text", "Marker Felt.ttf", 24);

 

TTF는 외곽선 기반으로 폰트를 렌더링하기 때문에 효율적이고 유연하다. 폰트의 윤곽을 계산해 렌더링하는 방식이기 때문에 한 파일로 다양한 스타일을 동적으로 적용할 수 있어 매우 편리하다.

 

굵기나 기울기, 밑줄 등의 스타일을 코드에서 바로 조정할 수 있고, 폰트를 확대하거나 축소해도 글자가 깨지지 않으며 가독성도 뛰어난 장점이 있다. 이런 이유로 동적 폰트는 다양한 스타일을 즉시 적용할 수 있으며, 특히 유연한 텍스트 처리가 필요한 경우에 유리하다.

 

비트맵 폰트보다 더 유연하지만 TTF는 렌더링 속도가 느리고 폰트 종류나 크기 같은 속성을 변경하는 것은 비용이 많이 드는 작업이다.

 

동일한 속성을 가진 여러 개의 라벨 객체가 필요하다면, TTFConfig 객체를 사용해 관리할 수 있다.

TTFConfig는 마치 유니티엔진의 UIToolkit의 클래스를 생각하면 편하다.

 

하나의 설정을 만들어두면 두고두고 재활용이 가능한것이 TTFConfig의 장점이다.

 

TTFConfig labelConfig;
labelConfig.fontFilePath = "fonts/LineSpeed.ttf";
labelConfig.fontSize = 16;
labelConfig.glyphs = GlyphCollection::DYNAMIC;
labelConfig.outlineSize = 0;
labelConfig.customGlyphs = nullptr;
labelConfig.distanceFieldEnabled = false;

auto myLabel = Label::createWithTTF(labelConfig, "My Label Text");

myLabel->setPosition(centerPos);

addChild(myLabel);

 

TTFConfig는 단순히 정보를 담는 컨텐이너 역할을 하기 때문에 Struct로 이루어져 있다.

TTFConfig에는 다양한 값들이 있기 때문에 몇가지만 살펴보도록 하자.

 

fontFilePath 폰트의 파일 경로를 지정해 주며 된다.Resource폴더의 fonts밑에 font를 보관 하기 때문에 "fonts/~~~.ttf"이렇게 적어주면 된다.
fontSize 말그대로 텍스트의 사이즈를 말한다.
outlineSize 글자 외곽선의 사이즈를 말한다.

 

이 밖에도 다앙햔  설정들이 있는데 자세하게 설명하면 내용이 많아져서 나중에 따로 TTFConfig에 대해 설명 하도록 하겠다.

 

 

Menu

Menu는 게임 화면에 표시되는 버튼이나 선택 가능한 UI 요소의 그룹을 관리하기 위한 클래스 이다. 주로 간단한 이벤트 처리하는 데 사용된다.

 

menu는 다음과 같이 만들수 있다.

auto myMenu = Menu::create();

 

MenuItem

 

메뉴 항목은 일반적으로 두 가지 상태를 가지며, 기본(normal) 상태와 선택(selected) 상태입니다. 메뉴 항목을 탭하거나 클릭하면 콜백(callback)이 실행됩니다. 이를 일종의 연쇄 반응(chain reaction)으로 생각할 수 있습니다.

auto buttonItem = MenuItemImage::create("button.png", "buttonPress.png", 
    CC_CALLBACK_0(GameScene::Print, this));

auto menu = Menu::create(closeItem, NULL);

addChild(menu, 1);

 

button이 기본 상태일때와 선택 상태일때의 이미지를 지정해주고, 어떤 메소드를 실행 시킬지 또한 지정해 주어야 한다.

 

menu를  Create할때 마지막에 NULL을 넣어주는데, Menu::Create()또한 가변 인자를 사용하기 때문에 끝을 알려주어야 해서 NULL을 넣어주어야 한다.

 

vector 자료형으로 menu를 만들수도 있다.

 Vector<MenuItem*> menuItemVector;

 auto closeItem = MenuItemImage::create("button.png", "buttonPress.png", 
     CC_CALLBACK_0(GameScene::Print, this));

 menuItemVector.pushBack(closeItem);

 auto menu = Menu::createWithArray(menuItemVector);

 addChild(menu, 1);

이렇게 만들면 Create할때 NULL을 넣어주지도 않고 만들수 있다.

 

그리고 vector로 관리 하기 때문에 여러 MenuItem을 통합적으로 관리 하기 편하다.

 

 

LAMDA

c++11이상 부터 람다함수를 사용할수 있다.

당연히 cocos2dx에서도 이를 지원해준다.람다를 이용하여 함수를 간단하게 만들수 있다.

   auto closeItem = MenuItemImage::create("button.png", "buttonPress.png",
       [&](Ref* sender) {
           CCLOG("this is beautiful world");
       });

 

이렇게 람다를 써써 간단한 함수를 만들수 있다.

 

UI에 대한 내용이 길기 때문에 여기서 끊고 다음 글에서 Button,CheckBox,Slider Bar 등에 대해 알아보도록 하자.