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성분)