typedef struct s_info { double pos_x; double pos_y; double dir_x; double dir_y; double plane_x; double plane_y; double moveSpeed; double rotSpeed; } t_info; typedef struct s_screen { void *mlx; void *win; t_img img; // t_pixel **pixel; // t_vec origin; // t_vec dir; // t_vec plane; double sin_unit; double cos_unit; double distance; t_info info; int width; int height; } t_screen; int worldMap[24][24]= { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,"> typedef struct s_info { double pos_x; double pos_y; double dir_x; double dir_y; double plane_x; double plane_y; double moveSpeed; double rotSpeed; } t_info; typedef struct s_screen { void *mlx; void *win; t_img img; // t_pixel **pixel; // t_vec origin; // t_vec dir; // t_vec plane; double sin_unit; double cos_unit; double distance; t_info info; int width; int height; } t_screen; int worldMap[24][24]= { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,"> typedef struct s_info { double pos_x; double pos_y; double dir_x; double dir_y; double plane_x; double plane_y; double moveSpeed; double rotSpeed; } t_info; typedef struct s_screen { void *mlx; void *win; t_img img; // t_pixel **pixel; // t_vec origin; // t_vec dir; // t_vec plane; double sin_unit; double cos_unit; double distance; t_info info; int width; int height; } t_screen; int worldMap[24][24]= { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1}, {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,">
#include "../../mlx_new/mlx.h"
#include <math.h>

typedef struct s_info
{
	double	pos_x;
	double	pos_y;
	double	dir_x;
	double	dir_y;
	double	plane_x;
	double	plane_y;
	double	moveSpeed;
	double	rotSpeed;
}				t_info;

typedef struct	s_screen
{
	void		*mlx;
	void		*win;
	t_img		img;
//	t_pixel		**pixel;
//	t_vec		origin;
//	t_vec		dir;
//	t_vec		plane;
	double		sin_unit;
	double		cos_unit;
	double		distance;
	t_info		info;
	int			width;
	int			height;
}				t_screen;

int worldMap[24][24]=
{
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};

void	verLine(t_screen *my_screen, int x, int y1, int y2, int color)
{
	int	y;

	y = y1;
	while (y <= y2)
	{
		mlx_pixel_put(my_screen->mlx, my_screen->win, x, y, color);
		y++;
	}
}

void	draw_pixel(t_screen *my_screen)
{
	int	x;

	x = 0; //
	while (x < my_screen->width) //화면에 보이는 x 좌표를 따라 0부터 screen의 끝까지 루프를 돌며 픽셀을 색칠한다.
	{//광선 위치 및 방향 지정
		double camera_x = 2 * x / (double)my_screen->width - 1; 
		//-1, -0.xx ... , 0, 1 (아래 광선을 아래에서 위로 훑기 위해 카메라를 비율로 설정)
		double rayDirX = my_screen->info.dir_x + my_screen->info.plane_x * camera_x;
		double rayDirY = my_screen->info.dir_y + my_screen->info.plane_y * camera_x;

		//지도 위 내 위치
		int mapX = (int)my_screen->info.pos_x;
		int mapY = (int)my_screen->info.pos_y;

		//현재 위치에서 다음 x 또는 y 측까지의 광선 길이
		double sideDistX;
		double sideDistY;

		 //하나의x 또는 y 측으로부터 다음 x 또는 y 측까지의 광선길이
		double deltaDistX = fabs(1 / rayDirX);
		double deltaDistY = fabs(1 / rayDirY);
		double perpWallDist;

		//x 또는 y 방향으로 걸을 방향(+1 또는 -1)
		int stepX;
		int stepY;

		int hit = 0; //광선이 벽을 맞았나?
		int side; //NS나 EW 벽이 맞았나?

		//스탭 및 초기 길이면을 계산합니다.
		if (rayDirX < 0)
		{
			stepX = -1;
			sideDistX = (my_screen->info.pos_x - mapX) * deltaDistX;
		}
		else
		{
			stepX = 1;
			sideDistX = (mapX + 1.0 - my_screen->info.pos_x) * deltaDistX;
		}
		if (rayDirY < 0)
		{
			stepY = -1;
			sideDistY = (my_screen->info.pos_y - mapY) * deltaDistY;
		}
		else
		{
			stepY = 1;
			sideDistY = (mapY + 1.0 - my_screen->info.pos_y) * deltaDistY;
		}
		//DDA를 구현
		while (hit == 0)
		{
			//다음 지도 사각형으로 이동, (x 방향 또는 y 방향)
			if (sideDistX < sideDistY)
			{
				sideDistX += deltaDistX;
				mapX += stepX;
				side = 0;
			}
			else
			{
				sideDistY += deltaDistY;
				mapY += stepY;
				side = 1;
			}
			//광선이 벽을 맞았는지 확인하기
			if (worldMap[mapX][mapY] > 0) hit = 1;
		}
		//카메라 방향에 투영된 거리 계산(유클리드 거리가 어안효과를 부여합니다.)
		if (side == 0)
			perpWallDist = (mapX - my_screen->info.pos_x + (1 - stepX) / 2) / rayDirX;
		else
			perpWallDist = (mapY - my_screen->info.pos_y + (1 - stepY) / 2) / rayDirY;

	ㅊ
		//벽색을 고르기
		int	color;
		if (worldMap[mapY][mapX] == 1)
			color = 0x00FF00;
		else if (worldMap[mapY][mapX] == 2)
			color = 0x005EFF;
		else if (worldMap[mapY][mapX] == 3)
			color = 0x00BBFF;
		else if (worldMap[mapY][mapX] == 4)
			color = 0xFFFFFF;
		else
			color = 0xFFFF00;

		//x와 y에게 밝고 어두운 면을 선사
		if (side == 1)
			color = color / 2;
		//스트라이프의 픽셀을 수직선으로 그린다.
		verLine(my_screen, x, drawStart, drawEnd, color);

		x++;
	}
}

int		main_loop(t_screen *my_screen)
{
	t_info info;

	info.pos_x = 10; // x와 y의 시작 점
	info.pos_y = 4;
	info.dir_x = -1; // 초기 방향벡터
	info.dir_y = 0;
	info.plane_x = 0; //2차원 레이케스터의 카메라 평면
	info.plane_y = 0.66;
	info.moveSpeed = 0.05; //속도
	info.rotSpeed = 0.05;
	my_screen->info = info;
	draw_pixel(my_screen);
	return (0);
}

int		main()
{
	t_screen	screen;
	t_screen	*my_screen;
	t_img		img;

	my_screen = &screen;
	my_screen->width = 1920;
	my_screen->height = 1080;

	my_screen->mlx = mlx_init(); //mlx 사용을 위해 가장 먼저 사용하는 함수다. 내 소프트웨어와 디스플레이를 연결해준다.
	my_screen->win = mlx_new_window(my_screen->mlx, my_screen->width, my_screen->height, "cub3D Start");//주어진 사이즈만큼의 빈창을 띄워줌
	my_screen->img.ptr = mlx_new_image(my_screen->mlx, my_screen->width, my_screen->height);//주어진 사이즈만큼 픽셀이미지를 초기화시켜준다.
	//my_screen->img.addr = (unsigned int*)mlx_get_data_addr(my_screen->img.ptr, \\
			&(my_screen->img.bits_per_pixel), &(my_screen->img.size_line), &(my_screen->img.endian));
	mlx_loop_hook(my_screen->mlx, &main_loop, my_screen);
	//mlx_hook(my_screen->mlx, X_EVENT_KEY_PRESS, 0, &key_press, &my_screen);
	mlx_loop(my_screen->mlx);//이벤트를 받기위해서 꼭 써야하는 함수이다. 키보드나 마우스로부터 받은 이벤트를 기다리는 무한루프이고, 이벤트에 연결되는 사용자정의 함수를 호출한다.
}

mlx_loop_hook

int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);

mlx_loop_hook()함수는 mlx_loop()함수가 동작하는 동안에 funct_ptr파라미터로 받은 함수를 계속 호출하게 됩니다. 고로, 만약 funct_ptr파라미터가 이미지를 그리는 함수라면 새로운 좌표값에 맞는 이미지를 다시 화면에 반영할 수 있게 되는 것입니다.

초기 위치 좌표에서의 카메라의 방향과 시야

double camera_x = 2 * x / (double)my_screen->width - 1; 
//-1, -0.xx ... , 0, 1
double rayDirX = my_screen->info.dir_x + my_screen->info.plane_x * camera_x;
//-1, -1, ... , -1, -1 (ray벡터의 x성분)
double rayDirY = my_screen->info.dir_y + my_screen->info.plane_y * camera_x;
//-0.66, -0.xx, ..., 0, 0.66 (ray벡터의 y성분)