42_cub3d/algo.c
2024-10-11 05:23:55 +02:00

247 lines
7.3 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* algo.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: greg <greg@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */
/* Updated: 2024/10/11 05:16:06 by greg ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
#include <math.h>
#include <stdio.h>
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