/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* algo.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: greg +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */ /* Updated: 2024/10/11 05:16:06 by greg ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" #include #include 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} }; static int initalgo(t_ray *ray) { ray->posX = 13; ray->posY = 10; ray->dirX = -1; ray->dirY = 0; ray->planeX = 0; ray->planeY = 0.66; // FOV de 66 degres ray->movespeed = 0.1; ray->rotspeed = 0.1; return (0); } static int render(t_ray *ray) { int x; double width = 640; double height = 480; int hit; int side; int *img_data = (int *)mlx_get_data_addr(ray->img_ptr, &(int){32}, &(int){width * 4}, &(int){0}); // clear image data ft_bzero(img_data, width * height * sizeof(int)); x = 0; while (x < width) { // position et direction du rayon ray->cameraX = 2 * x / width - 1; ray->raydirX = ray->dirX + ray->planeX * ray->cameraX; ray->raydirY = ray->dirY + ray->planeY * ray->cameraX; ray->mapX = (int)ray->posX; ray->mapY = (int)ray->posY; ray->deltadistX = (ray->raydirX == 0) ? 1e30 : fabs(1 / ray->raydirX); ray->deltadistY = (ray->raydirY == 0) ? 1e30 : fabs(1 / ray->raydirY); //calculate step and initial sideDist if (ray->raydirX < 0) { ray->stepX = -1; ray->sidedistX = (ray->posX - ray->mapX) * ray->deltadistX; } else { ray->stepX = 1; ray->sidedistX = (ray->mapX + 1.0 - ray->posX) * ray->deltadistX; } if (ray->raydirY < 0) { ray->stepY = -1; ray->sidedistY = (ray->posY - ray->mapY) * ray->deltadistY; } else { ray->stepY = 1; ray->sidedistY = (ray->mapY + 1.0 - ray->posY) * ray->deltadistY; } hit = 0; while(hit == 0) { //jump to next map square, either in x-direction, or in y-direction if(ray->sidedistX < ray->sidedistY) { ray->sidedistX += ray->deltadistX; ray->mapX += ray->stepX; side = 0; } else { ray->sidedistY += ray->deltadistY; ray->mapY += ray->stepY; side = 1; } //Check if ray has hit a wall if(worldMap[ray->mapX][ray->mapY] == 1) hit = 1; } if(side == 0) ray->perpwalldist = (ray->sidedistX - ray->deltadistX); else ray->perpwalldist = (ray->sidedistY - ray->deltadistY); //Calculate height of line to draw on screen int lineHeight = (int)(height / ray->perpwalldist); //calculate lowest and highest pixel to fill in current stripe int drawStart = -lineHeight / 2 + height / 2; if(drawStart < 0) drawStart = 0; int drawEnd = lineHeight / 2 + height / 2; if(drawEnd >= height) drawEnd = height - 1; // draw vertical line int y = 0; while (y <= drawStart) { img_data[y * (int)width + x] = 0x29f8ff;; y++; } y = drawStart; while (y <= drawEnd) { img_data[y * (int)width + x] = 0xFF0000; y++; } y++; while (y <= height) { img_data[y * (int)width + x] = 0xFF985C; y++; } x++; } // put image to window mlx_put_image_to_window(ray->mlx_ptr, ray->win_ptr, ray->img_ptr, 0, 0); return (0); } static int keypress(int keycode, t_ray *ray) { //move forward if no wall in front of you if (keycode == 119) { if (worldMap[(int)((ray->posX + ray->dirX * ray->movespeed))][(int)(ray->posY)] != 1) ray->posX += ray->dirX * ray->movespeed; if (worldMap[(int)(ray->posX)][(int)(ray->posY + ray->dirY * ray->movespeed)] != 1) ray->posY += ray->dirY * ray->movespeed; } //move backwards if no wall behind you if (keycode == 115) { if (worldMap[(int)(ray->posX - ray->dirX * ray->movespeed)][(int)(ray->posY)] != 1) ray->posX -= ray->dirX * ray->movespeed; if (worldMap[(int)(ray->posX)][(int)(ray->posY - ray->dirY * ray->movespeed)] != 1) ray->posY -= ray->dirY * ray->movespeed; } //rotate to the right if (keycode == 100) { //both camera direction and camera plane must be rotated ray->oldDirX = ray->dirX; ray->dirX = ray->dirX * cos(-ray->rotspeed) - ray->dirY * sin(-ray->rotspeed); ray->dirY = ray->oldDirX * sin(-ray->rotspeed) + ray->dirY * cos(-ray->rotspeed); ray->oldPlaneX = ray->planeX; ray->planeX = ray->planeX * cos(-ray->rotspeed) - ray->planeY * sin(-ray->rotspeed); ray->planeY = ray->oldPlaneX * sin(-ray->rotspeed) + ray->planeY * cos(-ray->rotspeed); } //rotate to the left if (keycode == 97) { //both camera direction and camera plane must be rotated ray->oldDirX = ray->dirX; ray->dirX = ray->dirX * cos(ray->rotspeed) - ray->dirY * sin(ray->rotspeed); ray->dirY = ray->oldDirX * sin(ray->rotspeed) + ray->dirY * cos(ray->rotspeed); ray->oldPlaneX = ray->planeX; ray->planeX = ray->planeX * cos(ray->rotspeed) - ray->planeY * sin(ray->rotspeed); ray->planeY = ray->oldPlaneX * sin(ray->rotspeed) + ray->planeY * cos(ray->rotspeed); } if (keycode == 65307) exit(0); // render the updated frame after key press render(ray); return (0); } int main(void) { t_ray ray; // Initialisation ray.mlx_ptr = mlx_init(); ray.win_ptr = mlx_new_window(ray.mlx_ptr, 640, 480, "cub3d"); ray.img_ptr = mlx_new_image(ray.mlx_ptr, 640, 480); initalgo(&ray); // hook keypress mlx_hook(ray.win_ptr, 2, 1L<<0, keypress, &ray); // render the initial frame render(&ray); // start the mlx loop mlx_loop(ray.mlx_ptr); return (0); } // https://github.com/iciamyplant/Cub3d-Linux // https://lodev.org/cgtutor/raycasting.html // https://www.youtube.com/watch?v=js7HW65MmNw&list=PL0H9-oZl_QOHM34HvD3DiGmwmj5X7GvTW