발전하는 춘배
[원고, SDL3](完) 6. 윈도우 오목 게임 만들기 - 메뉴화면, 종료화면, 게임 상태의 표현, cmake 써먹어보기, 컴파일 옵션들 이해해보기 본문
[원고, SDL3](完) 6. 윈도우 오목 게임 만들기 - 메뉴화면, 종료화면, 게임 상태의 표현, cmake 써먹어보기, 컴파일 옵션들 이해해보기
춘배0 2025. 8. 25. 22:48목표는 기본 메뉴화면과, 게임 종료 시 누가 이겼는지를 표시하는 종료 화면을 띄우는 거다. 기본 메뉴화면엔 게임 시작 버튼이 있고, 게임 종료 화면엔 다시하기 버튼을 만들어 보자.
시작은 gpt형님한테 도움을 받아본다.
게임 상태(state) 개념을 도입하는 게 제일 깔끔합니다.
라고 한다. 오 이런 개발 경험이 없는 사람 입장에서 gpt형님은 이런 게 가장 좋은 거 같다. 이런 식으로 할 수 있구나~를 제시해주니깐.
enum class GameState {
MENU, // 초기 화면
PLAYING, // 실제 게임
OVER
};
enum으로 게임 상태들을 정의한다.
class Game
{
private:
GameState state;
const SDL_FRect startButton = { 400, 550, 400, 100 }; // x,y,w,h
...
}
...
Game::Game(User user1, User user2) : state(GameState::MENU), user1(user1), user2(user2)
{
board = InitializeBoard();
gameOver = new GameOver();
isUser1Turn = true;
}
Game 클래스에 멤버로 추가한다. 생성자에서 초기화해준다.
추가로 버튼도 정의해준다.
아이디어는 이렇다.
매 프레임 일어나는 일(별거없음): 이벤트 스택 쌓인 거 처리(game.HandleEvent(e);) -> 렌더링(game.Render(renderer);) -> SDL_RenderPresent(renderer);
사실상 함수2개 호출이 다다.
모든 함수에서 state에 따라 분기시켜서 다른 걸 하게 하면 된다. 예를 들어
void Game::HandleEvent(const SDL_Event& e) {
if (state == GameState::MENU) {
if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
int mx = e.button.x;
int my = e.button.y;
if (mx >= startButton.x && mx <= startButton.x + startButton.w &&
my >= startButton.y && my <= startButton.y + startButton.h) {
state = GameState::PLAYING; // 게임 시작
}
}
} else if (state == GameState::PLAYING) {
if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
// 게임로직
}
} else if (state == GameState::OVER) {
if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
// 메뉴랑 사실상 동일
}
}
}
요런 식으로 state별로 다른 로직을 짜두는거다. 쉽다.
렌더링도 MENU state라면 메인화면 뿌려주고, PLAYING state라면 바둑판 뿌려주고 해주면 된다. 쉽다.



이대로 끝낼까 하다가 그래도 게임인데 텍스트 GUI정도는 있어야하는 게 아닌가 해서 알아보니 SDL_ttf 라이브러리가 따로 있다고.
귀찮지만 해보기로 했다.
https://github.com/libsdl-org/SDL_ttf/releases
Releases · libsdl-org/SDL_ttf
Support for TrueType (.ttf) font files with Simple Directmedia Layer. - libsdl-org/SDL_ttf
github.com
역시 라이브러리 설치 및 적용이 젤 어렵다.
처음 SDL3 설치했을 때처럼 zip파일 받아서 압축풀고 docs에 있는 방법대로 cmake 이용해서 빌드하려 했는데 실패. 이유는 SDL3을 못찾음.
gpt한테 물어봐서
cmake -S . -B build -DCMAKE_PREFIX_PATH="C:/SDL3/x86_64-w64-mingw32"
이렇게 했더니 SDL3 헤더랑 라이브러리 찾을 수 있게 됨.
바로 다음 문제: FreeType 의존성이 있기 때문에 이거도 설치해야함.
https://download.savannah.gnu.org/releases/freetype/?C=M&O=A
Index of /releases/freetype/
download.savannah.gnu.org
여기서 최신꺼 zip파일 설치해줌 압축풀고
mkdir build
cd build
cmake .. -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=C:/freetype
cmake --build . --config Release
cmake --install . --config Release
이렇게 했더니 C:/freetype에 include랑 lib 생겼음. 신기하다 cmake
드디어 SDL3_fft도 빌드가 가능해짐.
cmake -S . -B build -DCMAKE_PREFIX_PATH="C:/SDL3/x86_64-w64-mingw32;C:/freetype" -DCMAKE_INSTALL_PREFIX="C:/SDL3/SDL3_ttf-3.2.2/install" -DCMAKE_BUILD_TYPE=Release
cmake --build build
빌드성공
다시 오목프로젝트로 돌아와서
SDL3_ttf.dll 붙여주고
g++ src\*.cpp -o main.exe -Iinclude -I "C:\SDL3\x86_64-w64-mingw32\include" -I "C:\SDL3\SDL3_ttf-3.2.2\include" -L "C:\SDL3\x86_64-w64-mingw32\lib" -L "C:\SDL3\SDL3_ttf-3.2.2\build" -lSDL3 -lSDL3_ttf
경로 덕지덕지 붙여서 컴파일 성공.
하다보니깐 감이 온다.
알게된거:
-I 옵션: .h 헤더파일 들어 있는 경로 추가해줌. 컴파일러가 함수 선언을 알 수 있게 됨. 근데 -L 안 붙이면 링커가 함수 구현부를 못찾음.
-L 옵션: 함수 구현이 들어 있는 경로를 추가해줌. .a(정적 라이브러리), .dll(동적 라이브러리) 같은 파일들
-l 옵션: -L로 붙은 위치에서 실제로 어떤 라이브러리를 쓸 지 결정. 링커가 lib<name>.a 또는 lib<name>.dll.a 파일을 찾아서 연결해줌. 그니깐 위 커맨드로 컴파일하면 libSDL3.dll.a랑 libSDL3_ttf.dll.a를 써먹겠단 뜻.
디렉터리 들어가보니까 실제로 있었다! 깨달음을 얻었따..


아 그럼 굳이 omok디렉토리 안에 .dll을 복붙할 필요는 없었구만. 왜했더라 이거 생각해보면 처음에 뭐 모르니깐 gpt가 하란대로 했던 것 같다. 과감히 삭제. 했더니 이게왠걸 컴파일은 되는데 실행이안된다. 이유는?
.dll.a (임포트 라이브러리): 링커가 “이 함수는 DLL에 있다”라고 알려주는 역할.
그니깐 -lSDL3으로 써먹은 libSDL3.dll.a는 그 자체로 함수 구현이 들어있는 게 아니라 런타임에 필요하면 dll에서 갖다 써라~는 느낌.
아하 완벽히 이해했다.
마지막으로 궁금한 거. main.exe가 들어 있는 디렉토리와 동일한 디렉토리에 실제 dll파일이 있어야 하는 건지? 아니면 디렉토리가 달라도 쓸 수 있는 건지?
GPT형님의 답변:
- Windows는 LoadLibrary 규칙에 따라 DLL을 찾음:
- 실행 파일과 동일한 디렉토리 → 가장 우선
- Windows 시스템 디렉토리 (C:\Windows\System32)
- 현재 작업 디렉토리
- PATH 환경 변수에 등록된 디렉토리
그렇구만 그냥 디렉토리에 복붙해놓는 게 젤 맘편하겠다. 고민해결!
이제 후딱 실제 text 출력하고 끝내자.
https://www.freepascal-meets-sdl.net/rendering-text-with-fonts-sdl3_ttf-in-sdl3/
Rendering Text with Fonts (SDL3_ttf) - Free Pascal meets SDL
It is shown how text can be rendered by SDL3_ttf in Free Pascal using True Type Fonts.
www.freepascal-meets-sdl.net

그냥은 또 안 되고 이런 과정을 거쳐야 한다. 쉬운 일은 없구나. 그래도 이미지 보니까 이해가 좀 잘 된다.
https://infoarts.tistory.com/59
SDL2_ttf 사용하기
제가 SDL 라이브러리와 함께 많이 쓰는 라이브러리에는 SDL_image, SDL_ttf, SDL_net이 있습니다. 그중에 SDL2_ttf를 이용하여 FreeType 폰트를 출력하는 방법을 알아보겠습니다. SDL2_ttf 사이트: https://www.libsdl
infoarts.tistory.com
코드는 이거 참고해서 붙여넣었다. SDL3으로 넘어오면서 바뀐거 적용시켜서 성공.


이렇게 조잡한 오목게임 만들어봤따.
이룬 것
- SDL3 써먹어보기 (특히 Video, Event 카테고리의 API 맛보기 성공)
- SDL3_ttf 써먹어보기
- 그 과정에서 C/C++ 프로젝트에서 라이브러리 가져다 쓰는 법 부딪히면서 배움
- 컴파일-링킹 과정 상기. 특히 -I, -L, -l 옵션, .h, .a, .dll.a, .dll 확장자 이해.
- cmake 써먹어보기 (이해는1도못했음 사실) 그래도 써먹어봤다는 게 중요한 게 아닐까요?
- C++플젝 구조: include에 헤더파일 몰아넣고 src에 구현 몰아넣는 구조 써봄
- enum으로 (게임) 상태를 표현하고 그에 따라 분기시킨다는 아이디어 획득
요종도? 나름 재미있었따.
'.원고' 카테고리의 다른 글
| [원고, C++/OOP] 로그라이크 게임 만들어보기 2 - Map 구현하기 1 : World 클래스 도입 및 책임 부여, unordered_map의 rehash, unique_ptr (0) | 2026.02.08 |
|---|---|
| [원고, C++/OOP] 로그라이크 게임 만들어보기 1 - 클래스 헤더 파일 분리, enum class, 공격과 피해 책임 분리 (0) | 2026.02.07 |
| [원고, SDL3] 5. 윈도우 오목 게임 만들기 - 버그해결 (3) | 2025.08.25 |
| [원고, SDL3] 4. 윈도우 오목 게임 만들기 - SDL써서 그래픽 띄우기, 클릭이벤트 써먹기 (1) | 2025.08.24 |
| [원고, SDL3] 3. 윈도우 오목 게임 만들기 - 클래스 파일 분할, 분할컴파일 (3) | 2025.08.24 |
