-
Notifications
You must be signed in to change notification settings - Fork 1
02_04.WindowManagement
이번 글에서는 raylib의 core
모듈 (rcore.c
)에 정의된 게임 창과 커서 관련 함수들 중에 자주 사용되는 함수들에 대해 알아보자. raylib.h
헤더 파일에서 "Window and Graphics Device Functions"를 검색하면 게임 창과 커서와 관련된 나머지 함수들을 찾을 수 있다.
아래 함수들은 무슨 기능을 하는지 주석을 읽어보면 쉽게 이해할 수 있기 때문에 자세한 설명은 생략하도록 하겠다.
// 게임 창을 생성하고, OpenGL의 현재 상태를 초기화한다.
RLAPI void InitWindow(int width, int height, const char *title);
// 사용자가 지정한 게임 종료 키 또는 게임 창 닫기 버튼이 눌렸는지 확인한다.
RLAPI bool WindowShouldClose(void);
// 게임 창을 닫고, OpenGL과 관련된 메모리를 해제한다.
RLAPI void CloseWindow(void);
// 게임 창이 초기화되었는지 확인한다.
RLAPI bool IsWindowReady(void);
// 게임 창이 전체 화면 모드인지 확인한다.
RLAPI bool IsWindowFullscreen(void);
// 게임 창이 숨겨진 상태인지 확인한다.
RLAPI bool IsWindowHidden(void);
// 게임 창이 최소화 상태인지 확인한다.
RLAPI bool IsWindowMinimized(void);
// 게임 창이 최대화 상태인지 확인한다.
RLAPI bool IsWindowMaximized(void);
// 게임 창이 다른 모든 창보다 앞에 있는지 확인한다.
RLAPI bool IsWindowFocused(void);
// 게임 창의 크기가 최근 (이전 프레임)에 변경되었는지 확인한다.
RLAPI bool IsWindowResized(void);
/* ... */
// 게임 창의 가로 길이를 반환한다.
RLAPI int GetScreenWidth(void);
// 게임 창의 세로 길이를 반환한다.
RLAPI int GetScreenHeight(void);
이 함수들은 게임 창의 설정을 변경하는 함수들이다.
// 게임 창의 초기화 설정을 변경한다. 이 함수는 반드시 `InitWindow()` 호출 직전에 호출해야 하며,
// `InitWindow()` 이후에 게임 창의 설정을 변경하려면 `SetWindowState()` 함수를 이용해야 한다.
RLAPI void SetConfigFlags(unsigned int flags);
/* ... */
// 게임 창에서 주어진 비트 플래그에 대응하는 설정 값이 켜져 있는지 확인한다.
RLAPI bool IsWindowState(unsigned int flag);
// 게임 창의 설정 값을 주어진 비트 플래그 값으로 변경한다.
RLAPI void SetWindowState(unsigned int flags);
// 게임 창의 모든 설정 값을 초기화한다.
RLAPI void ClearWindowState(unsigned int flags);
여기서 비트 플래그란 여러 개의 참/거짓 값을 단 하나의 정수로 저장하여, 메모리 공간을 절약하는 방법이다. 이게 무슨 뜻이냐고? 일단 게임 창의 각 설정 값을 한번 살펴보자. 이해를 돕기 위해 16진수 값 옆에 그 값의 2진수 값도 같이 적어놓았다.
/* 게임 창의 각 설정을 나타내는 비트 플래그. */
typedef enum {
// 수직 동기화 활성화
FLAG_VSYNC_HINT = 0x00000040, /* 0b01000000 */
// 전체 화면 모드 활성화
FLAG_FULLSCREEN_MODE = 0x00000002, /* 0b00000010 */
// 게임 창의 크기 변경 허용
FLAG_WINDOW_RESIZABLE = 0x00000004, /* 0b00000100 */
/* ... */
// 안티-에일리어싱 (MSAA 4x) 기능 활성화
FLAG_MSAA_4X_HINT = 0x00000020, /* 0b00100000 */
/* ... */
} ConfigFlags;
게임 창의 설정을 자세히 보면, 각 설정 값이 활성화 또는 비활성화, 즉 참/거짓으로 나타낼 수 있는 값임을 알 수 있다. 만약 이 값들을 변수로 만들어서 저장하면 어떻게 될까? 우리가 사용하는 대부분의 컴퓨터에서 가장 작은 자료형 (char
, unsigned char
)의 크기는 1바이트인데, 겨우 4개의 참/거짓 값을 저장하기 위해 4바이트의 메모리 공간을 사용해야 하는 것이다.
unsigned char vsync_hint = false;
unsigned char fullscreen_mode = false;
unsigned char window_resizable = false;
unsigned char msaa_4x_hint = false;
이러한 문제를 해결하기 위한 방법이 바로 비트 플래그이다. 비트 플래그는 하나의 참/거짓 값을 저장하기 위해 정수형 값에서 단 1비트 (참이면 1, 거짓이면 0)만을 사용하는 방법이다. 아래 예시를 통해 비트 플래그가 왜 메모리 공간을 효율적으로 사용하게 해주는지 알아보자.
/*
16진수: `0x00000060`
2진수: `0b01100000`
--------------------
왼쪽에서부터 두 번째 비트 (`0b01000000`)는 수직 동기화를
나타내는 옵션 (`FLAG_VSYNC_HINT`)인데, 이 비트가 1이므로
수직 동기화 옵션을 활성화한다.
또한 왼쪽에서부터 세 번째 비트 (`0b0010000`)는
안티-에일리어싱 (MSAA 4x) 기능 사용을 나타내는 옵션인데,
이 비트가 1이므로 안티-에일리어싱 기능을 활성화한다.
나머지 비트는 모두 0이므로, 위 2개 이외의 게임 창 옵션을
모두 비활성화한다.
*/
unsigned char flags = 0x00000060;
우리는 각 옵션에 대한 변수를 만드는 대신, 특정 비트의 값을 1 또는 0으로 설정하는 방식으로 게임 창의 모든 설정 값을 단 1바이트에 저장할 수 있다. raylib에는 총 14개의 게임 창 설정 값이 존재하는데, 만약 이 값들을 1바이트짜리 변수에 하나씩 저장한다면 총 14바이트의 메모리 공간을 사용하게 될 것이다. 하지만 비트 플래그를 사용하면 최소 14비트의 공간을 저장할 수 있는 short
나 int
변수 하나만을 사용하여, 게임 창의 모든 설정 값을 저장할 수 있고, 메모리 공간도 약 4배 이상 절약할 수 있다!
이제 SetConfigFlags()
와 SetWindowState()
의 사용법을 간단히 알아보자. 이 두 함수들의 차이는 바로 SetConfigFlags()
는 반드시 InitWindow()
호출 직전에만 사용할 수 있지만, SetWindowState()
는 게임 창 초기화 이후에도 사용할 수 있다는 것이다. 또한 SetWindowState()
는 SetConfigFlags()
와 다르게, 설정할 수 있는 게임 창 설정 값이 제한되어 있다.
int main(void) {
// 안티-에일리어싱 (MSAA 4x) 기능을 활성화한다.
SetConfigFlags(FLAG_MSAA_4X_HINT);
// 게임 창을 생성하고, OpenGL의 현재 상태를 초기화한다.
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "6pm-crew/play");
/* ... */
// 게임 창을 닫고, OpenGL과 관련된 메모리를 해제한다.
CloseWindow();
}
여러 개의 옵션을 동시에 활성화하고 싶다면, 비트 OR 연산자 (|
)를 사용한다.
// 수직 동기화 기능과 안티-에일리어싱 (MSAA 4x) 기능을 활성화한다.
SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT);
아래 함수들은 커서의 동작을 제어하거나, 커서 관련 속성 값을 제공한다. 자세한 설명은 생략하도록 하겠다.
// 마우스 커서를 보여준다.
RLAPI void ShowCursor(void);
// 마우스 커서를 숨긴다.
RLAPI void HideCursor(void);
// 마우스 커서가 숨겨진 상태인지 확인한다.
RLAPI bool IsCursorHidden(void);
// 마우스 커서를 움직일 수 있게 한다.
RLAPI void EnableCursor(void);
// 마우스 커서를 움직이지 못하게 한다.
RLAPI void DisableCursor(void);
// 마우스 커서가 게임 화면 위에 있는지 확인한다.
RLAPI bool IsCursorOnScreen(void);
- 오픈 소스 소프트웨어란?
- Git과 버전 관리 시스템
- GitHub를 이용한 저장소 호스팅
- 프로젝트의 기여 및 관리
- 라이브러리 소개
- 개발 환경 구축
- 첫 번째 프로그램
- 게임 창과 커서 관리
- 프레임, 시간과 타이머
- 픽셀, 선분과 기본 도형
- 마우스와 키보드 입력
- 벡터 글꼴과 비트맵 글꼴
- 이미지와 텍스처의 사용
- 카메라와 렌더 텍스처
- 충돌 감지와 충돌 해결
- 효과음과 음악 재생
- 그 외 유용한 함수