mlx는 X-Window에 관한 지식 없이도 쉽게 그래픽 관련 소프트웨어를 만들 수 있도록 하는 라이브러리이다. 간단하게 window를 생성하고, image를 띄우고, 입력장치등을 관리할 수 있다. mlx 내부에서 제공하는 기능들은 OpenGL과 AppKit을 이용한다. 따라서 프로그램을 생성할 때, OpenGL과 AppKit을 프레임 워크로 이용하겠다고 알려주어야 한다.
X-Window
X-Window는 디스플레이 장치에 창을 표시하며 마우스와 키보드 등의 입력 장치의 상호작용 등을 관리해 GUI 환경의 구현을 위한 기본적인 프레임워크를 제공한다.
AppKit
AppKit은 GUI를 위한 프레임워크이다.
mlx를 사용하기 위해 가장 먼저 사용하는 함수이다. 소프트웨어와 디스플레이 장치 연결을 생성해 준다.
void *mlx_init();
리턴값 : 성공시 현재 소프트웨어와 디플레이를 연결한 포인터를 반환, 실패시 NULL
반환
창(window)을 생성한다. 창에 대한 식별자 포인터를 반환하는데, 참고로 창의 식별자는 고유값이라 여러 개의 다른 창을 제어할 수 있다.
void *mlx_new_window(void *mlx_ptr, int width, int height, char *title);
리턴값 : 창에 대한 식별자 포인터를 반환, 실패시 NULL
반환
키보드나 마우스 등 입력장치에서 이벤트가 발생하면 콜백 함수를 호출한다. x_event에 넣을 값으로 여러 종류가 있는데, 세브젝트에선 키 입력만 받으면 되므로 KEYPRESS = 2
로 2를 넣어주면 된다. Mac OS X에서는 x_mask 값이 사용되지 않는다.(mask는 좀 더 세부적인 입력값이라고 한다.) mlx_hook 함수만으로 키보드 버튼, 마우스 버튼 등 이벤트를 모두 등록할 수 있다.
int mlx_hook(void *win_ptr, int x_event, int x_mask, int (*funct)(), void *param);
리턴값 : 0
이벤트를 받기 위해서 꼭 써야 하는 함수로, 입력 장치를 관리하고 처리한다. 입력장치의 이벤트를 기다리는 무한루프이다. 그래픽 시스템은 양방향성을 가진다. 한쪽에서는 창에 이미지를 그리고, 한쪽에서는 입력 이벤트를 받아 처리한다.이벤트를 캐치하면 mlx_hook 함수에 등록된 콜백 함수를 호출하고 이벤트를 처리한다.
int mlx_loop (void *mlx_ptr);
리턴값 : 없음
xpm 파일을 이미지에대한 식별자 포인터로 저장한다. 이미지를 사용하고 싶을 때 이 포인터를 사용하면 된다.
void *mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
리턴값 : 성공시 이미지에 대한 식별자를 포인터로 반환, 실패시 NULL
을 반환
창에 이미지를 출력한다. 출력할 x좌표와 y좌표가 필요하다. 좌표를 사용할 때, 이미지의 크기에 맞춰 사용해야 하므로 x * IMG_SIZE
, y * IMG_SIZE
이렇게 사용해야 한다.
int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y);
창을 삭제하는 함수이다.
int mlx_destroy_window(void *mlx_ptr, void *win_ptr);
구현은 크게 네 단계로 나뉜다.
0
, 1
, C
, E
, P
로 구성된 1차원 맵을 2차원 이중배열로 만들어 준다. 그 과정에서 맵이 유요한 지 체크해야 한다. 직사각형인지, 벽으로 둘러싸여 있는지, 각각의 구성이 빠짐 없는지, 위에 언급한 것 외의 인자가 들어오는지 유효성 검사를 해준다.
🥲 여기가 처리해야 할 예외사항이 많고 좀 까다롭기 때문에 여기까지만 해도 반은 왔다고 할 수 있다!
창을 띄우고, 이미지를 셋팅한다.
2차원 배열을 한 줄씩 읽으면서 이미지를 창에 그려준다. 2, 3단계는 mlx에 대해서 알고 있으면 어렵지 않다!
w
, a
, s
, d
키가 입력되면 플레이어를 움직여야 한다. 따라서 입력값에 따른 dst가 움직일 수 있는 곳인지(벽인지, 아이템을 다 먹지 않았는데 출구로 간다던지를) 먼저 체크하고, 움직일 수 있는 곳이면 걸음수++
;을 하고 다시 3번 함수로 가서 그려준다. 움직일 수 없는 곳이면 return ;
시킨다.
과제를 완료하고 나니 그렇게 어려웠던 게 아닌 것 같은데... 플레이어가 움직이지 않는다던가, 말록 할당 에러처리, 메모리누수 등 생각할 게 많은 과제였었다. 특히 제출 바로 전에 strjoin에서 그렇게 많은 메모리 누수가 날 줄이야..!
☄️ libft 함수를 사용할 때에는 꼭꼭 다시 한 번 꼼꼼하게 체크해봐야겠다.
그래도 오랜만에 귀엽고 깜찍한 이미지를 쓰고, 눈에 확확 보이는 과제였어서 재밌었다. 또 함수, 파일을 (norminette에 맞춰^^*) 기능별로 분리하고 정리하면서 더 성장했다!!👍