diff --git a/Makefile b/Makefile index c3df77e..82d5c97 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: greg +#+ +:+ +#+ # +# By: mcolonna +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2024/07/29 13:08:42 by greg #+# #+# # -# Updated: 2024/10/15 12:53:36 by marvin ### ########.fr # +# Updated: 2024/10/15 13:01:09 by mcolonna ### ########.fr # # # # **************************************************************************** # diff --git a/algo.c b/algo.c index fbc1eec..b175ac3 100644 --- a/algo.c +++ b/algo.c @@ -6,49 +6,17 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */ -/* Updated: 2024/10/15 12:54:19 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 13:13:13 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" -#include -#include -#include -#include void *g_mlx = NULL; void *g_win = NULL; t_ray g_ray; -// int worldMap[mapWidth][mapHeight]= -// { -// {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,1,1,1,1,1,0,0,0,0,1,0,1,0,1,0,0,0,1}, -// {1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1}, -// {1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,0,1,0,1,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,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, -// {1,1,1,1,1,1,1,1,1,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} -// }; - -int worldMap[mapWidth][mapHeight]= +int worldMap[mapWidth][mapHeight] = { {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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, diff --git a/algo.h b/algo.h index 3dcacea..338701d 100644 --- a/algo.h +++ b/algo.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/09/30 15:45:59 by grobledo #+# #+# */ -/* Updated: 2024/10/15 12:54:12 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 13:10:34 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,8 +19,9 @@ #include "Minilibx/mlx.h" #include "Minilibx/mlx_int.h" # include "Libft/libft.h" -#define mapWidth 24 // cases -#define mapHeight 24 // cases + +#define mapWidth 24 // cases (TODO test) +#define mapHeight 24 // cases (TODO test) #define MOVE_SPEED 0.1 // cases #define PI 3.1415926535 #define ROT_SPEED (PI / 16) // rad @@ -37,6 +38,7 @@ typedef struct s_ray double posX; // pos player on map (cases) double posY; + // player rotation (rad) double rot; } t_ray; diff --git a/move.c b/move.c index e15b271..6321ef9 100644 --- a/move.c +++ b/move.c @@ -6,68 +6,64 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/15 12:47:34 by mcolonna #+# #+# */ -/* Updated: 2024/10/15 12:52:05 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 13:27:10 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" +static int move_forward(void) +{ + double dirX, dirY; + vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); + + if (worldMap[(int)((g_ray.posX + dirX * MOVE_SPEED))][(int)(g_ray.posY)] != 1) + g_ray.posX += dirX * MOVE_SPEED; + if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY + dirY * MOVE_SPEED)] != 1) + g_ray.posY += dirY * MOVE_SPEED; + return(0); +} + +static int move_backward(void) +{ + double dirX, dirY; + vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); + + if (worldMap[(int)(g_ray.posX - dirX * MOVE_SPEED)][(int)(g_ray.posY)] != 1) + g_ray.posX -= dirX * MOVE_SPEED; + if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY - dirY * MOVE_SPEED)] != 1) + g_ray.posY -= dirY * MOVE_SPEED; + return(0); +} + +static int move_right(void) +{ + g_ray.rot += ROT_SPEED; + return (0); +} + +static int move_left(void) +{ + g_ray.rot -= ROT_SPEED; + return (0); +} + int keypress(int keycode) { - double dirX, dirY, planeX, planeY; - vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); - vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV); - - //move forward if no wall in front of you if (keycode == XK_Up || keycode == XK_z || keycode == XK_w) - { - if (worldMap[(int)((g_ray.posX + dirX * MOVE_SPEED))][(int)(g_ray.posY)] != 1) - g_ray.posX += dirX * MOVE_SPEED; - if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY + dirY * MOVE_SPEED)] != 1) - g_ray.posY += dirY * MOVE_SPEED; - } - //move backwards if no wall behind you + move_forward(); if (keycode == XK_Down || keycode == XK_s) - { - if (worldMap[(int)(g_ray.posX - dirX * MOVE_SPEED)][(int)(g_ray.posY)] != 1) - g_ray.posX -= dirX * MOVE_SPEED; - if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY - dirY * MOVE_SPEED)] != 1) - g_ray.posY -= dirY * MOVE_SPEED; - } - //rotate to the right + move_backward(); if (keycode == XK_Right || keycode == XK_d) - { - g_ray.rot += ROT_SPEED; - // double oldDirX; - // double oldPlaneX; - // //both camera direction and camera plane must be rotated - // oldDirX = dirX; - // dirX = dirX * cos(-ROT_SPEED) - dirY * sin(-ROT_SPEED); - // dirY = oldDirX * sin(-ROT_SPEED) + dirY * cos(-ROT_SPEED); - // oldPlaneX = planeX; - // planeX = planeX * cos(-ROT_SPEED) - planeY * sin(-ROT_SPEED); - // planeY = oldPlaneX * sin(-ROT_SPEED) + planeY * cos(-ROT_SPEED); - } - //rotate to the left + move_right(); if (keycode == XK_Left || keycode == XK_q || keycode == XK_a) - { - g_ray.rot -= ROT_SPEED; - // double oldDirX; - // double oldPlaneX; - // //both camera direction and camera plane must be rotated - // oldDirX = dirX; - // dirX = dirX * cos(ROT_SPEED) - dirY * sin(ROT_SPEED); - // dirY = oldDirX * sin(ROT_SPEED) + dirY * cos(ROT_SPEED); - // oldPlaneX = planeX; - // planeX = planeX * cos(ROT_SPEED) - planeY * sin(ROT_SPEED); - // planeY = oldPlaneX * sin(ROT_SPEED) + planeY * cos(ROT_SPEED); - } - + move_left(); if (keycode == XK_Escape) - exit(0); - - printf("x:%f y:%f\n", g_ray.posX, g_ray.posY); - // render the updated frame after key press + { + mlx_destroy_window(g_mlx, g_win); + exit(0); // TODO leaks? + } + // render the updated frame after key pressd draw_screen(); return (0); } diff --git a/render.c b/render.c index fb370dd..125ad45 100644 --- a/render.c +++ b/render.c @@ -5,13 +5,135 @@ /* +:+ +:+ +:+ */ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/10/15 12:40:52 by mcolonna #+# #+# */ -/* Updated: 2024/10/15 12:51:25 by mcolonna ### ########.fr */ +/* Created: 2024/10/14 14:55:05 by greg #+# #+# */ +/* Updated: 2024/10/15 13:52:35 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" +static void calculate_perpwalldist3(int x, + double *raydirX, double *raydirY, + double *deltadistX, double *deltadistY) +{ + double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1; + double dirX; + double dirY; + double planeX; + double planeY; + vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); + vector_from_rotation(&planeX, &planeY, g_ray.rot + PI / 2, 1); + *raydirX = dirX + planeX * ray_direction; + *raydirY = dirY + planeY * ray_direction; + *deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / *raydirX); + *deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / *raydirY); +} + +static void calculate_perpwalldist2(int x, + double *sidedistX, double *sidedistY, + double *deltadistX, double *deltadistY, + int *stepX, int *stepY) +{ + int mapX = (int)g_ray.posX; + int mapY = (int)g_ray.posY; + double raydirX; + double raydirY; + + calculate_perpwalldist3(x, &raydirX, &raydirY, deltadistX, deltadistY); + if (raydirX < 0) + { + *stepX = -1; + *sidedistX = (g_ray.posX - mapX) * *deltadistX; + } + else + { + *stepX = 1; + *sidedistX = (mapX + 1.0 - g_ray.posX) * *deltadistX; + } + if (raydirY < 0) + { + *stepY = -1; + *sidedistY = (g_ray.posY - mapY) * *deltadistY; + } + else + { + *stepY = 1; + *sidedistY = (mapY + 1.0 - g_ray.posY) * *deltadistY; + } +} + +/// @brief Calculate the distance of the wall perpendicularly to the camera +/// plane. +/// +/// @param x Ray direction x between 0 and 1. +/// @return Result. +static double calculate_perpwalldist(int x) +{ + int mapX = (int)g_ray.posX; + int mapY = (int)g_ray.posY; + bool side; + double sidedistX; + double sidedistY; + double deltadistX; + double deltadistY; + int stepX; + int stepY; + calculate_perpwalldist2(x, &sidedistX, &sidedistY, &deltadistX, &deltadistY, &stepX, &stepY); + while(worldMap[mapX][mapY] != 1) + { + // jump to next map square, either in x-direction, or in y-direction + if(sidedistX < sidedistY) + { + sidedistX += deltadistX; + mapX += stepX; + side = false; + } + else + { + sidedistY += deltadistY; + mapY += stepY; + side = true; + } + } + double perpwalldist; + if(!side) + perpwalldist = (sidedistX - deltadistX); + else + perpwalldist = (sidedistY - deltadistY); + return (perpwalldist); +} + +/// @brief Draw a vertical line according to the ray direction x. +/// +/// @param x Ray direction x between 0 and 1. +static void draw_vertical_line(int x, u_int32_t *img_data) +{ + double perpwalldist = calculate_perpwalldist(x); + int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist); + int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2; + if(drawStart < 0) + drawStart = 0; + int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2; + if(drawEnd >= SCREEN_HEIGHT) + drawEnd = SCREEN_HEIGHT - 1; + int y = 0; + while (y < drawStart) + { + img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING; + y++; + } + while (y < drawEnd) + { + img_data[y * SCREEN_WIDTH + x] = COLOR_WALL; + y++; + } + while (y < SCREEN_HEIGHT) + { + img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR; + y++; + } +} + int render(u_int32_t *img_data) { int x; // px @@ -27,114 +149,7 @@ int render(u_int32_t *img_data) x = 0; while (x < SCREEN_WIDTH) { - // case player on map (cases) - int mapX = (int)g_ray.posX; - // case player on map (cases) - int mapY = (int)g_ray.posY; - - // vector ray direction (1) - double raydirX, raydirY; - { - // ray direction in [-1;+1]. the highter the more to the right (1) - double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1; - raydirX = dirX + planeX * ray_direction; - raydirY = dirY + planeY * ray_direction; - } - - // longueur du rayon dans une même colonne de cases (cases) - double deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / raydirX); - // longueur du rayon dans une même ligne de cases (cases) - double deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / raydirY); - - // longueur du rayon entre pos actuelle et pos du prochain coté ouest ou est d'une box - double sidedistX; - // longueur du rayon entre pos actuelle et pos du prochain coté nord ou sub d'une box - double sidedistY; - - // direction du rayon sur x (+1 or -1) - int stepX; - // direction du rayon sur y (+1 or -1) - int stepY; - - if (raydirX < 0) - { - stepX = -1; - sidedistX = (g_ray.posX - mapX) * deltadistX; - } - else - { - stepX = 1; - sidedistX = (mapX + 1.0 - g_ray.posX) * deltadistX; - } - if (raydirY < 0) - { - stepY = -1; - sidedistY = (g_ray.posY - mapY) * deltadistY; - } - else - { - stepY = 1; - sidedistY = (mapY + 1.0 - g_ray.posY) * deltadistY; - } - - bool hit = false; - bool side; - while(!hit) - { - // jump to next map square, either in x-direction, or in y-direction - if(sidedistX < sidedistY) - { - sidedistX += deltadistX; - mapX += stepX; - side = false; - } - else - { - sidedistY += deltadistY; - mapY += stepY; - side = true; - } - // check if ray has hit a wall - if(worldMap[mapX][mapY] == 1) - hit = true; - } - - // calcul lenght of ray (shortest perpendicular distance between wall and camera plane) (1) - double perpwalldist; - if(!side) - perpwalldist = (sidedistX - deltadistX); - else - perpwalldist = (sidedistY - deltadistY); - - // calculate height of line to draw on screen (px) - int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist); - - // calculate lowest and highest pixel to fill in current stripe - int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2; - if(drawStart < 0) - drawStart = 0; - int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2; - if(drawEnd >= SCREEN_HEIGHT) - drawEnd = SCREEN_HEIGHT - 1; - - // draw vertical line - int y = 0; - while (y < drawStart) - { - img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING; - y++; - } - while (y < drawEnd) - { - img_data[y * SCREEN_WIDTH + x] = COLOR_WALL; - y++; - } - while (y < SCREEN_HEIGHT) - { - img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR; - y++; - } - + draw_vertical_line(x, img_data); x++; }