키보드 입력으로 위에서 생성한 삼각형을 움직여보도록 하겠습니다.
miniLibX에서 키보드, 마우스 등으로부터 입력을 받기 위해서 이벤트 개념을 알아야 합니다. 이벤트는 프로그램에 의해 감지되고 처리될 수 있는 동작이나 사건을 말합니다(위키백과). miniLibX는 이벤트를 처리하기 위해서 mlx_loop()
라는 루프문이 필요합니다. 이 함수는 이벤트의 수신을 기다리고 있다가, 해당 이벤트를 생성시킵니다.
#include "mlx/mlx.h"
#include <stdio.h>
#include <stdlib.h>
#define UP 126
#define DOWN 125
#define LEFT 123
#define RIGHT 124
#define ESC 53
#define KeyPress 2
#define KeyRelease 3
typedef struct s_data
{
void *mlx;
void *mlx_win;
int width, height;
int x, y;
int up, down, left, right;
void *img;
char *addr;
int bits_per_pixel;
int line_length;
int endian;
} t_data;
void my_mlx_pixel_put(t_data *data, int x, int y, int color)
{
char *dst;
dst = data->addr
+ (y * data->line_length + x * (data->bits_per_pixel / 8));
*(unsigned int*)dst = color;
}
int ft_move(t_data *data)
{
if (data->left == 1 && data->x > 0)
{
data->x -= 3;
printf("x = %d, y= %d\n", data->x, data->y);
}
if (data->right == 1 && data->x + 100 < data->width)
{
data->x += 3;
printf("x = %d, y= %d\n", data->x, data->y);
}
if (data->up == 1 && data->y > 0)
{
data->y -= 3;
printf("x = %d, y= %d\n", data->x, data->y);
}
if (data->down == 1 && data->y + 100 < data->height)
{
data->y += 3;
printf("x = %d, y= %d\n", data->x, data->y);
}
return (0);
}
int ft_key_press(int keycode, t_data *data)
{
if (keycode == ESC)
{
mlx_destroy_window(data->mlx, data->mlx_win);
exit(0);
}
if (keycode == LEFT)
data->left = 1;
if (keycode == RIGHT)
data->right = 1;
if (keycode == UP)
data->up = 1;
if (keycode == DOWN)
data->down = 1;
return (0);
}
int ft_key_release(int keycode, t_data *data)
{
if (keycode == LEFT)
data->left = 0;
if (keycode == RIGHT)
data->right = 0;
if (keycode == UP)
data->up = 0;
if (keycode == DOWN)
data->down = 0;
return (0);
}
int ft_draw(t_data *data)
{
// printf("ft_draw!\n");
int i;
int j;
int k;
int x = data->x;
int y = data->y;
for (i = 0; i < data->width; i++)
{
for (j = 0; j < data->height; j++)
my_mlx_pixel_put(data, i, j, 0x00000000);
}
for (i = x, k = 99; i < x + 50; i++, k -= 2)
{
for (j = y + k; j < y + 100; j++)
my_mlx_pixel_put(data, i, j, 0x0000FF00);
}
for (i = x + 50, k = 0; i < x + 100; i++, k += 2)
{
for (j = y + k; j < y + 100; j++)
my_mlx_pixel_put(data, i, j, 0x0000FF00);
}
mlx_put_image_to_window(data->mlx, data->mlx_win, data->img, 0, 0);
return (0);
}
int main_loop(t_data *data)
{
ft_draw(data);
ft_move(data);
return (0);
}
int main(void)
{
t_data data;
data.mlx = mlx_init();
data.width = 600;
data.height = 400;
data.mlx_win = mlx_new_window(data.mlx, data.width, data.height, "miniRT");
data.img = mlx_new_image(data.mlx, 600, 400);
data.addr = mlx_get_data_addr(data.img, &data.bits_per_pixel, &data.line_length, &data.endian);
mlx_put_image_to_window(data.mlx, data.mlx_win, data.img, 0, 0);
data.x = 250;
data.y = 150;
mlx_hook(data.mlx_win, KeyPress, 1L<<0, ft_key_press, &data);
mlx_hook(data.mlx_win, KeyRelease, 1L<<1, ft_key_release, &data);
mlx_loop_hook(data.mlx, main_loop, &data);
mlx_loop(data.mlx);
return (0);
}
mlx_hook()
함수로 이벤트를 생성할 수 있습니다. mlx_key_hook()
, mlx_mouse_hook()
, mlx_expose_hook()
의 각각 특정 이벤트에 대한 정의를 mlx_hook()
을 사용하여 모두 처리할 수 있습니다.
int mlx_hook(void *win_ptr, int x_event, int x_mask, int (*funct_ptr)(), void *param);
이벤트를 생성하려는 윈도우의 식별자를 win_ptr
파리미터에 지정해 줍니다. x_event
, x_mask
파라미터로 이벤트 상황을 지정해줍니다(X11/X.h 문서 참고). miniLibX의 mlx_hook()
함수에서는 파라미터로 x_mask
를 받지만 내부에서 사용을 하지 않으므로 0으로 값을 지정해도 무관합니다. funct_ptr
파라미터는 해당 이벤트가 발생할 때, 실행할 함수의 주소를 받는 함수 포인터 파라미터입니다. param
파라미터는 funct_ptr
로 호출한 함수에 필요한 파라미터 데이터를 보내주는 파라미터입니다.
생성한 이벤트를 수신하기 위해서는 mlx_loop()
함수가 필요합니다. mlx_loop()
함수는 이벤트를 수신하고 연동된 함수를 호출하는 동작을 반복적으로 수행합니다.
이벤트를 수신하고 연동된 함수를 호출하여 키 입력에 대한 이미지의 x, y 좌표값 변경 작업을 성공적으로 수행했다 하더라도 화면에는 아직 반영이 되지 않았습니다. 다음 프레임에 변경된 사항을 업데이트 해주기 위해 필요한 함수가 바로 mlx_loop_hook()
함수입니다.
int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);
mlx_ptr
파라미터는 연결 식별자입니다. funct_ptr
파라미터, param
파라미터는 mlx_hook()
의 funct_ptr
파라미터, param
파라미터와 동일합니다.
mlx_loop_hook()
함수는 mlx_loop()
함수가 동작하는 동안 funct_ptr
파라미터로 받은 함수를 반복적으로 호출합니다. 그렇기 때문에 이미지를 그리는 함수를 funct_ptr
파라미터에 넣어주면 새로운 좌표값에 맞는 이미지를 다시 화면에 반영할 수 있게됩니다.
ft_libgfx AKA b_gfx overload
https://github.com/qst0/ft_libgfx#minilibx
42 Docs
https://harm-smits.github.io/42docs/libs/minilibx/getting_started.html
cub3d I-yohai github
https://github.com/l-yohai/cub3d/blob/master/mlx_example/05_sprite_raycast.c