reorganize all files (only renamings)

This commit is contained in:
mcolonna 2024-10-31 16:06:33 +01:00
parent 609bd90b54
commit 878de1098b
27 changed files with 21 additions and 14 deletions

91
src/algo.c Normal file
View file

@ -0,0 +1,91 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* algo.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mc <mc@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */
/* Updated: 2024/10/31 15:26:48 by mc ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
#include "input.h"
#include <stdio.h>
void *g_mlx = NULL;
void *g_win = NULL;
t_map g_map;
t_player g_player;
// t_tex g_tex;
static void load_textures(t_tex *tex)
{
tex->tex_width = 64;
tex->tex_height = 64;
tex->textures[0] = mlx_xpm_file_to_image(g_mlx, "textures/north.xpm",
&tex->tex_width, &tex->tex_height);
tex->textures[1] = mlx_xpm_file_to_image(g_mlx, "textures/south.xpm",
&tex->tex_width, &tex->tex_height);
tex->textures[2] = mlx_xpm_file_to_image(g_mlx, "textures/east.xpm",
&tex->tex_width, &tex->tex_height);
tex->textures[3] = mlx_xpm_file_to_image(g_mlx, "textures/west.xpm",
&tex->tex_width, &tex->tex_height);
}
void draw_screen(void)
{
void *img_ptr;
u_int32_t *img_data;
t_tex tex;
load_textures(&tex);
img_ptr = mlx_new_image(g_mlx, SCREEN_WIDTH, SCREEN_HEIGHT);
img_data = get_data_addr(img_ptr);
if (!img_data)
exit(1);
render(img_data, &tex);
mlx_put_image_to_window(g_mlx, g_win, img_ptr, 0, 0);
mlx_destroy_image(g_mlx, img_ptr);
}
static void loop(void)
{
move();
if (g_input_actions.quit)
{
mlx_destroy_window(g_mlx, g_win);
exit(0);
}
draw_screen();
}
static int loop_hook(void *param)
{
(void)param;
timedloop(loop);
return (0);
}
int main(int argc, char *argv[])
{
g_mlx = mlx_init();
input_init();
if (argc != 2)
{
printf("Syntax: %s <map.cub>\n", argv[0]);
return (1);
}
if (!map_from_file(&g_map, argv[1]))
return (1);
g_win = mlx_new_window(g_mlx, SCREEN_WIDTH, SCREEN_HEIGHT, "cub3d");
mlx_hook(g_win, KeyPress, KeyPressMask, keypress, NULL);
mlx_hook(g_win, KeyRelease, KeyReleaseMask, keyrelease, NULL);
mlx_loop_hook(g_mlx, loop_hook, NULL);
draw_screen();
mlx_loop(g_mlx);
return (0);
}

18
src/color.c Normal file
View file

@ -0,0 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* color.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 17:04:56 by mcolonna #+# #+# */
/* Updated: 2024/10/15 16:26:52 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map.h"
t_color color_from_rgb(int red, int green, int blue)
{
return (red << 16 | green << 8 | blue);
}

52
src/input.c Normal file
View file

@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* input.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/17 14:43:36 by mcolonna #+# #+# */
/* Updated: 2024/10/17 16:05:50 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "input.h"
#include <X11/keysym.h>
#include "algo.h"
t_input_actions g_input_actions;
static void set_action(int keycode, bool value)
{
if (keycode == XK_Up || keycode == XK_z || keycode == XK_w)
g_input_actions.up = value;
if (keycode == XK_Down || keycode == XK_s)
g_input_actions.down = value;
if (keycode == XK_Right || keycode == XK_d)
g_input_actions.right = value;
if (keycode == XK_Left || keycode == XK_q || keycode == XK_a)
g_input_actions.left = value;
if (keycode == XK_Escape)
g_input_actions.quit = value;
}
int keypress(int keycode)
{
set_action(keycode, true);
return (0);
}
int keyrelease(int keycode)
{
set_action(keycode, false);
return (0);
}
void input_init(void)
{
g_input_actions.down = false;
g_input_actions.up = false;
g_input_actions.left = false;
g_input_actions.right = false;
g_input_actions.quit = false;
}

123
src/map1.c Normal file
View file

@ -0,0 +1,123 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 17:12:58 by mcolonna #+# #+# */
/* Updated: 2024/10/15 17:22:53 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map.h"
#include "map_utils.h"
#include "stream.h"
#include "read_all_text.h"
#include "libft.h"
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
static bool map_from_file2(t_map *dest, t_stream *stream, int fd)
{
bool success;
stream->i = 0;
success = read_map(dest, stream);
if (success)
{
success = check_map(dest);
if (!success)
map_destroy(dest);
}
close(fd);
free((void *)stream->str);
map_init_objects(dest);
return (success);
}
bool map_from_file(t_map *dest, const char *file)
{
int fd;
t_stream stream;
if (ft_strncmp(file + ft_strlen(file) - 4, ".cub", 5))
{
write_err("File extension must be .cub\n", NULL);
return (false);
}
fd = open(file, O_RDONLY);
if (fd < 0)
{
write_err("Can't open '", file, "': ", strerror(errno), "\n",
NULL);
return (false);
}
stream.str = read_all_text(fd);
if (!stream.str)
{
write_err("Can't read file.\n", NULL);
close(fd);
return (false);
}
return (map_from_file2(dest, &stream, fd));
}
void map_destroy(t_map *map)
{
free((void *)map->texture_east);
free((void *)map->texture_west);
free((void *)map->texture_north);
free((void *)map->texture_south);
free(map->cases);
}
static bool check_map2(const t_map *map, unsigned int x, unsigned int y)
{
unsigned int x2;
unsigned int y2;
const t_map_case *c;
c = &map->cases[y * map->width + x];
if (c->inside && c->wall != WALL)
{
if (x == 0 || x == map->width - 1
|| y == 0 || y == map->height - 1)
return (write_err("Map is not surrounded by walls\n", NULL), false);
x2 = x - 2;
while (++x2 < x + 2)
{
y2 = y - 2;
while (++y2 < y + 2)
{
if (x < map->width && y < map->height
&& !map->cases[y2 * map->width + x2].inside)
return (write_err("Map is not surrounded by walls\n", NULL),
false);
}
}
}
return (true);
}
// TODO check player
bool check_map(const t_map *map)
{
unsigned int x;
unsigned int y;
x = -1;
while (++x < map->width)
{
y = -1;
while (++y < map->height)
{
if (!check_map2(map, x, y))
return (false);
}
}
return (true);
}

27
src/map2.c Normal file
View file

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/01 17:12:58 by mcolonna #+# #+# */
/* Updated: 2024/10/15 16:44:40 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map.h"
#include "map_utils.h"
#include "stream.h"
#include "read_all_text.h"
#include "libft.h"
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
const t_map_case *map_get_case(const t_map *map, int x, int y)
{
return (&map->cases[y * map->width + x]);
}

25
src/map_mapping.c Normal file
View file

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_mapping.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/04 12:05:21 by mcolonna #+# #+# */
/* Updated: 2024/10/15 17:19:26 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_mapping.h"
#include "player.h"
#include <stdlib.h>
const t_map_mapping_element g_map_mapping[] = {
{' ', {false, EMPTY, {NULL, NULL, NULL, NULL}}},
{'0', {true, EMPTY, {NULL, NULL, NULL, NULL}}},
{'1', {true, WALL, {NULL, NULL, NULL, NULL}}},
{'N', {true, EMPTY, {init_player_n, NULL, NULL, NULL}}},
{'S', {true, EMPTY, {init_player_s, NULL, NULL, NULL}}},
{'E', {true, EMPTY, {init_player_e, NULL, NULL, NULL}}},
{'W', {true, EMPTY, {init_player_w, NULL, NULL, NULL}}},
{'\0', {true, EMPTY, {NULL, NULL, NULL, NULL}}}};

139
src/map_utils1.c Normal file
View file

@ -0,0 +1,139 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_utils1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/03 15:02:09 by mc #+# #+# */
/* Updated: 2024/10/17 17:59:05 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_utils.h"
#include "map.h"
#include "map_mapping.h"
#include <stdlib.h>
bool read_color_parameter(const char *name, t_color *dest,
t_stream *stream, bool *redefined)
{
unsigned int rgb[3];
bool err;
t_stream old;
old = *stream;
err = false;
read_expected_string(name, stream, &err);
if (!read_blank(stream))
err = true;
read_unsigned(&rgb[0], stream, &err);
read_expected_string(",", stream, &err);
read_unsigned(&rgb[1], stream, &err);
read_expected_string(",", stream, &err);
read_unsigned(&rgb[2], stream, &err);
read_expected_string("\n", stream, &err);
if (!err && *dest != 0xFF000000)
{
*redefined = true;
write_err("Parameter '", name, "' was defined several times\n", NULL);
}
else if (!err)
*dest = color_from_rgb(rgb[0], rgb[1], rgb[2]);
else
*stream = old;
return (!err);
}
bool read_string_parameter(const char *name, const char **dest,
t_stream *stream, bool *redefined)
{
char *r;
bool err;
t_stream old;
old = *stream;
err = false;
r = NULL;
read_expected_string(name, stream, &err);
if (!read_blank(stream))
err = true;
read_until('\n', &r, stream, &err);
read_expected_string("\n", stream, &err);
if (!err && *dest)
{
*redefined = true;
write_err("Parameter '", name, "' was defined several times\n", NULL);
}
if (*redefined || err)
{
*stream = old;
free(r);
}
else
*dest = r;
return (!err);
}
static void read_map2(t_map *dest, bool *err, bool *rdf)
{
dest->cases = NULL;
dest->color_ceiling = 0xFF000000;
dest->color_floor = 0xFF000000;
dest->texture_east = NULL;
dest->texture_west = NULL;
dest->texture_north = NULL;
dest->texture_south = NULL;
*err = false;
*rdf = false;
}
bool read_map(t_map *dest, t_stream *stream)
{
bool err;
bool rdf;
int old_stream_i;
read_map2(dest, &err, &rdf);
while (!rdf && !err && stream->str[stream->i])
{
old_stream_i = stream->i;
if ((read_expected_string("\n", stream, &err), err)
&& !read_string_parameter("NO", &dest->texture_north, stream, &rdf)
&& !read_string_parameter("SO", &dest->texture_south, stream, &rdf)
&& !read_string_parameter("WE", &dest->texture_west, stream, &rdf)
&& !read_string_parameter("EA", &dest->texture_east, stream, &rdf)
&& !read_color_parameter("F", &dest->color_floor, stream, &rdf)
&& !read_color_parameter("C", &dest->color_ceiling, stream, &rdf))
{
stream->i = old_stream_i;
err = !read_map_description(dest, stream);
break ;
}
err = false;
}
if (!rdf && !dest->cases)
err = (write_err("Map description missing\n", NULL), true);
(rdf || err) && (map_destroy(dest), false);
return (!err && !rdf && dest->cases);
}
void map_init_objects(t_map *map)
{
t_point_int pos;
int i;
pos.x = 0;
while (pos.x < (int)map->width)
{
pos.y = 0;
while (pos.y < (int)map->height)
{
i = pos.y * map->width + pos.x;
if (map->cases[i].object.init)
map->cases[i].object.init(&map->cases[i].object.data, pos);
pos.y++;
}
pos.x++;
}
}

105
src/map_utils2.c Normal file
View file

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map_utils2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/04 15:12:08 by mcolonna #+# #+# */
/* Updated: 2024/10/15 16:27:41 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "map_utils.h"
#include "map_mapping.h"
#include "map.h"
#include <stdlib.h>
/// @brief Read the map description to get the dimensions.
/// The map must be at least 1x1.
///
/// @param map The .width and .height members will be set.
/// @param stream Stream to use.
/// @return true if success, false if error.
static bool get_map_dimensions(t_map *map, t_stream *stream)
{
unsigned int x;
unsigned int y;
map->width = 0;
map->height = 0;
y = 0;
while (stream->str[stream->i])
{
x = 0;
while (stream->str[stream->i] && stream->str[stream->i] != '\n')
{
stream->i++;
x++;
}
if (x > map->width)
map->width = x;
if (stream->str[stream->i] == '\n')
stream->i++;
y++;
}
map->height = y;
return (map->width > 0 && map->height > 0);
}
bool get_case(t_map_case *dest, char name)
{
int i;
char tmp[2];
i = -1;
while (g_map_mapping[++i].name)
{
if (name == g_map_mapping[i].name)
{
*dest = g_map_mapping[i].value;
return (true);
}
}
tmp[0] = name;
tmp[1] = '\0';
write_err("Character '", tmp, "' unexpected\n", NULL);
return (false);
}
void fill_zeros(void *dest, size_t size)
{
size_t i;
i = -1;
while (++i < size)
((char *)dest)[i] = '\0';
}
bool read_map_description(t_map *map, t_stream *stream)
{
t_stream stream2;
unsigned int x;
unsigned int y;
stream2 = *stream;
if (!get_map_dimensions(map, &stream2))
return (false);
map->cases = malloc((map->width * map->height) * sizeof(t_map_case));
y = -1;
fill_zeros(map->cases, (map->width * map->height) * sizeof(t_map_case));
while (++y < map->height)
{
x = 0;
while (stream->str[stream->i] && stream->str[stream->i] != '\n')
{
if (!get_case(&map->cases[y * map->width + x],
stream->str[stream->i]))
return (false);
stream->i++;
x++;
}
stream->i++;
}
return (true);
}

80
src/move.c Normal file
View file

@ -0,0 +1,80 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* move.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/15 12:47:34 by mcolonna #+# #+# */
/* Updated: 2024/10/17 15:06:43 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
#include "input.h"
static void push_from_wall(t_point_int c)
{
if (map_get_case(&g_map, c.x, c.y)->wall == EMPTY)
return ;
if (g_map.player.pos.x < c.x + 1 + HITBOX && g_map.player.pos.x > c.x + 1)
g_map.player.pos.x = c.x + 1 + HITBOX;
if (g_map.player.pos.x > c.x - HITBOX && g_map.player.pos.x < c.x)
g_map.player.pos.x = c.x - HITBOX;
if (g_map.player.pos.y < c.y + 1 + HITBOX && g_map.player.pos.y > c.y + 1)
g_map.player.pos.y = c.y + 1 + HITBOX;
if (g_map.player.pos.y > c.y - HITBOX && g_map.player.pos.y < c.y)
g_map.player.pos.y = c.y - HITBOX;
}
static void push_from_walls(void)
{
t_point_int c;
t_point_int p;
p.x = g_map.player.pos.x;
p.y = g_map.player.pos.y;
c.x = p.x - 1;
c.y = p.y;
push_from_wall(c);
c.x = p.x + 1;
c.y = p.y;
push_from_wall(c);
c.x = p.x;
c.y = p.y - 1;
push_from_wall(c);
c.x = p.x;
c.y = p.y + 1;
push_from_wall(c);
}
static int move_forward(int factor)
{
t_point_double dir;
vector_from_rotation(&dir, g_map.player.rot, 1);
g_map.player.pos.x += dir.x * MOVE_SPEED * factor;
g_map.player.pos.y += dir.y * MOVE_SPEED * factor;
push_from_walls();
return (0);
}
static int rotate(int factor)
{
g_map.player.rot += PI / ROT_SPEED_DIVIDE_PI * factor;
return (0);
}
// TODO leaks when quit?
void move(void)
{
if (g_input_actions.up && !g_input_actions.down)
move_forward(+1);
if (g_input_actions.down && !g_input_actions.up)
move_forward(-1);
if (g_input_actions.right && !g_input_actions.left)
rotate(+1);
if (g_input_actions.left && !g_input_actions.right)
rotate(-1);
}

46
src/player.c Normal file
View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* player.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/15 17:33:11 by mcolonna #+# #+# */
/* Updated: 2024/10/15 17:38:27 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "player.h"
#include "utils.h"
#include "algo.h"
static void init_player(t_point_int pos, double rot)
{
g_map.player.pos.x = pos.x + 0.5;
g_map.player.pos.y = pos.y + 0.5;
g_map.player.rot = rot;
}
void init_player_n(void **data, t_point_int pos)
{
(void)data;
init_player(pos, 0);
}
void init_player_s(void **data, t_point_int pos)
{
(void)data;
init_player(pos, PI);
}
void init_player_w(void **data, t_point_int pos)
{
(void)data;
init_player(pos, 3 * PI / 2);
}
void init_player_e(void **data, t_point_int pos)
{
(void)data;
init_player(pos, PI / 2);
}

95
src/read_all_text.c Normal file
View file

@ -0,0 +1,95 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_all_text.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 16:18:35 by mcolonna #+# #+# */
/* Updated: 2024/10/15 16:28:22 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "read_all_text.h"
#include "map.h"
#include "libft.h"
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
/// @brief Concatenate *dest and src and put the result in *dest.
///
/// *dest is alloc'd to contain the result value.
///
/// the old *dest is freed only if the function succeds.
///
/// src doesn't have to be nul-terminated, instead n is the size of src.
///
/// @return true if success, false if error.
static bool strconcat(char **dest, char *src, int n)
{
const int len_dest = ft_strlen(*dest);
char *old_dest;
int i;
old_dest = *dest;
*dest = malloc((len_dest + n + 1) * sizeof(char));
if (!*dest)
return (false);
i = -1;
while (old_dest[++i])
(*dest)[i] = old_dest[i];
while (i < len_dest + n)
{
(*dest)[i] = src[i - len_dest];
i++;
}
(*dest)[i] = '\0';
free(old_dest);
return (true);
}
/// @brief If the string isn't empty and isn't ended by a '\\n', add one and
/// return the result.
///
/// str is either returned directly, or another freeable pointer is returned
/// and str is freed.
///
/// @return Return the result or NULL if error.
static char *add_endline_if_necessary(char *str)
{
char *endline;
if (str[0] == '\0' || str[ft_strlen(str) - 1] == '\n')
return (str);
endline = malloc(1 * sizeof(char));
if (!endline)
return (free(str), NULL);
endline[0] = '\n';
if (!strconcat(&str, endline, 1))
return (free(str), NULL);
return (str);
}
char *read_all_text(int fd)
{
char buf[BUFFER_SIZE];
int n;
char *r;
r = malloc(sizeof(char));
if (!r)
return (NULL);
r[0] = '\0';
n = 1;
while (n)
{
n = read(fd, buf, BUFFER_SIZE);
if (n < 0 || (n && !strconcat(&r, buf, n)))
{
free(r);
return (NULL);
}
}
return (add_endline_if_necessary(r));
}

146
src/render.c Normal file
View file

@ -0,0 +1,146 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: grobledo <grobledo@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/14 14:55:05 by greg #+# #+# */
/* Updated: 2024/10/24 14:27:52 by grobledo ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
#include <stdio.h>
static void calculate_perpwalldist3(int x,
t_point_double *deltadist,
t_ray *ray)
{
const double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1;
t_point_double plane;
t_point_double dir;
vector_from_rotation(&dir, g_map.player.rot, 1);
vector_from_rotation(&plane, g_map.player.rot + PI / 2, 1);
ray->dir.x = dir.x + plane.x * ray_direction;
ray->dir.y = dir.y + plane.y * ray_direction;
deltadist->x = 1e30;
if (ray->dir.x != 0)
deltadist->x = fabs(1 / ray->dir.x);
deltadist->y = 1e30;
if (ray->dir.y != 0)
deltadist->y = fabs(1 / ray->dir.y);
}
static void calculate_perpwalldist2(int x,
t_point_double *sidedist,
t_point_double *deltadist,
t_point_int *step,
t_ray *ray)
{
const int map_x = (int)g_map.player.pos.x;
const int map_y = (int)g_map.player.pos.y;
calculate_perpwalldist3(x, deltadist, ray);
if (ray->dir.x < 0)
{
step->x = -1;
sidedist->x = (g_map.player.pos.x - map_x) * deltadist->x;
}
else
{
step->x = 1;
sidedist->x = (map_x + 1.0 - g_map.player.pos.x) * deltadist->x;
}
if (ray->dir.y < 0)
{
step->y = -1;
sidedist->y = (g_map.player.pos.y - map_y) * deltadist->y;
}
else
{
step->y = 1;
sidedist->y = (map_y + 1.0 - g_map.player.pos.y) * deltadist->y;
}
}
/// @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, t_ray *ray)
{
t_point_int map_pos;
t_point_double sidedist;
t_point_double deltadist;
t_point_int step;
map_pos.x = (int)g_map.player.pos.x;
map_pos.y = (int)g_map.player.pos.y;
calculate_perpwalldist2(x, &sidedist, &deltadist, &step, ray);
while (map_get_case(&g_map, map_pos.x, map_pos.y)->wall == EMPTY)
{
if (sidedist.x < sidedist.y)
{
sidedist.x += deltadist.x;
map_pos.x += step.x;
ray->side = false;
continue ;
}
sidedist.y += deltadist.y;
map_pos.y += step.y;
ray->side = true;
}
if (!ray->side)
return (sidedist.x - deltadist.x);
return (sidedist.y - deltadist.y);
}
/// @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,
t_ray *ray, t_tex *tex)
{
const double perpwalldist = calculate_perpwalldist(x, ray);
const int line_height = (int)(SCREEN_HEIGHT / perpwalldist);
int draw_start;
int draw_end;
int y;
ft_init_texture(perpwalldist, ray, tex);
draw_start = -line_height / 2 + SCREEN_HEIGHT / 2;
if (draw_start < 0)
draw_start = 0;
draw_end = line_height / 2 + SCREEN_HEIGHT / 2;
if (draw_end >= SCREEN_HEIGHT)
draw_end = SCREEN_HEIGHT - 1;
y = 0;
while (y++ < SCREEN_HEIGHT)
{
if (y < draw_start)
img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING;
else if (y < draw_end)
{
draw_wall(tex, ray, line_height, x, y, img_data);
}
else
img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR;
}
}
int render(u_int32_t *img_data, t_tex *tex)
{
int x;
t_ray ray;
x = 0;
while (x < SCREEN_WIDTH)
{
draw_vertical_line(x, img_data, &ray, tex);
x++;
}
return (0);
}

51
src/render2.c Normal file
View file

@ -0,0 +1,51 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: grobledo <grobledo@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/24 14:26:22 by grobledo #+# #+# */
/* Updated: 2024/10/24 14:27:37 by grobledo ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
void ft_init_texture(const double perpwalldist, t_ray *ray, t_tex *tex)
{
if (ray->side == 0 && ray->dir.x < 0)
tex->tex_dir = 0;
if (ray->side == 0 && ray->dir.x >= 0)
tex->tex_dir = 1;
if (ray->side == 1 && ray->dir.y < 0)
tex->tex_dir = 2;
if (ray->side == 1 && ray->dir.y >= 0)
tex->tex_dir = 3;
if (ray->side == 0)
ray->wallx = g_map.player.pos.y + perpwalldist \
* ray->dir.y;
else
ray->wallx = g_map.player.pos.x + perpwalldist \
* ray->dir.x;
ray->wallx -= floor((ray->wallx));
}
void draw_wall(t_tex *tex, t_ray *ray, const int line_height, int x,
int y, u_int32_t *img_data)
{
u_int32_t color;
u_int32_t *texture_data;
tex->tex_y = ((y - (-line_height / 2 + SCREEN_HEIGHT / 2)) \
* tex->tex_height) / line_height;
tex->tex_x = (int)(ray->wallx * (double)tex->tex_width);
if (ray->side == 0 && ray->dir.x > 0)
tex->tex_x = tex->tex_width - tex->tex_x - 1;
if (ray->side == 1 && ray->dir.y < 0)
tex->tex_x = tex->tex_height - tex->tex_x - 1;
texture_data = (u_int32_t *)mlx_get_data_addr(tex->textures[tex->tex_dir],
&tex->bpp, &tex->size_line, &tex->endian);
color = texture_data[tex->tex_x * tex->tex_width + tex->tex_y];
img_data[y * SCREEN_WIDTH + x] = color;
}

105
src/stream.c Normal file
View file

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/02 14:08:10 by mcolonna #+# #+# */
/* Updated: 2024/10/17 16:02:33 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "stream.h"
#include <stdlib.h>
void read_expected_string(const char *str, t_stream *stream, bool *err)
{
int i;
if (*err)
return ;
read_blank(stream);
i = 0;
while (str[i])
{
if (str[i] != stream->str[stream->i])
{
*err = true;
return ;
}
i++;
stream->i++;
}
return ;
}
/// @brief Check if a character is a digit.
/// @param c Character to check.
/// @return true if the character is a digit, false if not.
/// false if the character is '\0'.
static bool is_digit(char c)
{
return (c >= '0' && c <= '9');
}
void read_unsigned(unsigned int *dest, t_stream *stream, bool *err)
{
int r;
if (*err)
return ;
read_blank(stream);
if (!is_digit(stream->str[stream->i]))
{
*err = true;
return ;
}
r = 0;
while (is_digit(stream->str[stream->i]))
{
r = r * 10 + stream->str[stream->i] - '0';
stream->i++;
}
*dest = r;
}
void read_until(char c, char **dest, t_stream *stream, bool *err)
{
int len;
int i;
if (*err)
return ;
read_blank(stream);
len = 0;
while (stream->str[stream->i + len] && stream->str[stream->i + len] != c)
len++;
*dest = malloc((len + 1) * sizeof(char));
if (!*dest)
{
*err = true;
return ;
}
i = 0;
while (stream->str[stream->i] && stream->str[stream->i] != c)
{
(*dest)[i] = stream->str[stream->i];
i++;
stream->i++;
}
(*dest)[i] = '\0';
}
bool read_blank(t_stream *stream)
{
if (stream->str[stream->i] != ' '
&& stream->str[stream->i] != '\t')
return (false);
while (
stream->str[stream->i] == ' '
|| stream->str[stream->i] == '\t'
)
stream->i++;
return (true);
}

71
src/utils.c Normal file
View file

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/15 12:38:40 by mcolonna #+# #+# */
/* Updated: 2024/10/17 16:36:14 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "algo.h"
#include <stdarg.h>
void vector_from_rotation(t_point_double *vec, double angle, double norm)
{
vec->x = sin(angle) * norm;
vec->y = -cos(angle) * norm;
}
void write_err(const char *str, ...)
{
va_list args;
va_start(args, str);
write(2, "Error\n", 6);
while (str)
{
write(2, str, ft_strlen(str));
str = va_arg(args, const char *);
}
}
/* FOR BONUS
static long get_nanos(void)
{
struct timespec ts;
timespec_get(&ts, TIME_UTC);
return ((long)ts.tv_sec * 1000000000L + ts.tv_nsec);
}
void timedloop(void (*f)(void))
{
static long last_time = 0;
const long new_time = get_nanos();
static bool checked = false;
if (new_time - last_time >= 1000000000L / FPS)
{
if (checked)
last_time += 1000000000L / FPS;
else
last_time = new_time;
checked = false;
f();
}
else
checked = true;
}
*/
void timedloop(void (*f)(void))
{
static int ticks;
if (ticks % 100 == 0)
f();
ticks++;
}

31
src/utils2.c Normal file
View file

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/29 14:02:37 by mcolonna #+# #+# */
/* Updated: 2024/10/29 14:12:14 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "utils.h"
#include "mlx.h"
u_int32_t *get_data_addr(void *img_ptr)
{
int bpp;
int size_line;
int endian;
u_int32_t *r;
r = (u_int32_t *)mlx_get_data_addr(img_ptr, &bpp, &size_line, &endian);
if (bpp != 32 || endian != 0)
{
write_err("Wrong bpp or wrong endian when using mlx_get_data_addr().\n",
NULL);
return (NULL);
}
return (r);
}