Giter Site home page Giter Site logo

cub3d's Introduction

cub3d

Get Started

  • Implement raycasting in a simple video game
git clone [email protected]:Bima42/cub3d.git
make
./cub3d maps/map.cub

  • Use W, A, S, D key to move

  • Use left and right arrow to rotate camera

  • Esc quit the game

  • FIND MY GENERATOR HERE

Resume

  • First part was the parsing
  • Then, we split works in two parts : initialisation part (graphics, mlx ...) and raycasting part

Parsing

Map file

  • Extension file is .cub only
  • Begin by texture path (N, S, E, W)
  • Then some rgb data for ceiling and floor
  • Empty lines can be found between those datas

Map

  • Must be surrounded by '1', filled by '0'
  • Only one player spawn (N, S, E or W indicate player orientation)
  • Q for exit map

Map Checker

For every rows and colums (x and y) :

  • Start with skip white spaces
  • Then we have to hit a wall
  • We skip all char except wall (1) until white space or \0
  • If the char in pos - 1 is not a wall, it's an error
  • The fact is if we hit a wall we have to found another one, walls works by pair. If the second wall was not hit, row (or column) is false

Example for the x axis

int	control_axis_x(char **map, int y, int max_y)
{
	int	x;

	x = 0;
	if (y == max_y)
		return (1);
	if (map[y][x] != '\0')
	{
		skip_white_space(map[y], &x);
		while (map[y][x] == WALL && map[y][x] != '\0')
		{
			while (map[y][x] != '\0' && !is_w_space(map[y][x]))
				x++;
			if (map[y][x - 1] != WALL)
				return (0);
			skip_white_space(map[y], &x);
		}
		if (map[y][x] == '\0')
			return (control_axis_x(map, y + 1, max_y));
		else
			return (0);
	}
	return (0);
}
  • During this check, we extract the higher x and y to reformat_map, using white_spaces to reformat and put every lines at the same length.

  • Last line is filled with \0.

Raycasting

Explanation

  • Transforming a limited form of data into a three-dimensional projection with the help of tracing rays from the view point into the viewing volume.
  • Rays can be cast and traced in groups based on certain geometric constraints.
  • A ray from the pixel through the camera is obtained and the intersection of all objects in the picture is computed.

  • There some steps to cast rays:

    • 1 : Based on the viewing angle, subtract 30 degrees (half of the FOV).
    • 2 : Starting from column 0.
    • 3 : Cast a ray.
    • 4 : Trace the ray until it hits a wall.
    • 5 : Record the distance to the wall (the distance = length of the ray).
    • 6 : Add the angle increment so that the ray moves to the right
    • 7 : Repeat steps from step 3 with a column+1. We gonna cast one ray per unit width
  • We have to create a maze world that has the following geometric constraints:

    • Walls are always at 90° angle with the floor.
    • Walls are made of cubes that have the same size.
    • Floor is always flat.
  • Need to define some attributes :

    • Player/viewer’s height, player’s field of view (FOV), and player’s position.
    • Projection plane’s dimension.
    • Relationship between player and projection plane.
    • FOV of 60 is generally a good choice.
    • Player height reprensent half of window height.
void	raycasting(t_game *game)
{
	game->column = 0;
	game->rays.ang = game->p.vis + FOV / 2;
	while (game->column < WIN_W)
	{
		check_rays_angle(game);
		horizontal_raycasting(game);
		vertical_raycasting(game);
		draw(game);
		game->rays.ang -= FOV / (double)WIN_W;
		game->column++;
	}
}
  • WARNING : You want to protect the player to go outside the 360 degrees available for rotation.
void check_rays_angle(t_game *game)
{
	while (game->rays.ang >= 360)
		game->rays.ang -= 360;
	while (game->rays.ang < 0)
		game->rays.ang += 360;
}
  • To ensure that each ray stops at the first wall touched, it is necessary to carry out a horizontal and vertical check

Horizontal Check

double	horizontal_raycasting(t_game *game)
{
	game->rays.tan = tan(deg_to_rad(game->rays.ang));
	if (game->rays.ang > EAST && game->rays.ang < WEST)
	{
		game->rays.step_y = -TILE;
		game->rays.hit_y = floor(game->p.y / TILE) * TILE - 0.00001;
	}
	else
	{
		game->rays.step_y = TILE;
		game->rays.hit_y = floor(game->p.y / TILE) * TILE + TILE;
	}
	game->rays.hit_x = game->p.x
		+ (game->p.y - game->rays.hit_y) / game->rays.tan;
	if (game->rays.ang == NORTH || game->rays.ang == SOUTH)
		game->rays.step_x = 0;
	else
		game->rays.step_x = TILE / game->rays.tan;
	if (game->rays.ang > WEST)
		game->rays.step_x *= -1;
	digital_differential_analyzer(game);
	return (sqrt(square((game->p.x - game->rays.hit_x))
			+ square((game->p.y - game->rays.hit_y))));
}

Vertical Check

double	vertical_raycasting(t_game *game)
{
	game->rays.tan = tan(deg_to_rad(game->rays.ang));
	if (game->rays.ang < NORTH || game->rays.ang > SOUTH)
	{
		game->rays.step_x = TILE;
		game->rays.hit_x = floor(game->p.x / TILE) * TILE + TILE;
	}
	else
	{
		game->rays.step_x = -TILE;
		game->rays.hit_x = floor(game->p.x / TILE) * TILE - 0.00001;
	}
	game->rays.hit_y = game->p.y
		+ (game->p.x - game->rays.hit_x) * game->rays.tan;
	if (game->rays.ang == WEST || game->rays.ang == EAST)
		game->rays.step_y = 0;
	else
		game->rays.step_y = TILE * (game->rays.tan * -1);
	if (game->rays.ang >= NORTH && game->rays.ang <= SOUTH)
		game->rays.step_y *= -1;
	digital_differential_analyzer(game);
	return (sqrt(square((game->p.x - game->rays.hit_x))
			+ square((game->p.y - game->rays.hit_y))));
}

Digital Differential Analyzer

  • This algorithm is used to progress by step in each checker (vertical and horizontal)
  • We have to move for 1 Tile width for horizontal checker, and 1 Tile height for vertical checker
void	digital_differential_analyzer(t_game *game)
{
	game->map_pos_x = game->rays.hit_x / (int)TILE;
	game->map_pos_y = game->rays.hit_y / (int)TILE;
	while (game->map_pos_x > 0 && game->map_pos_x < game->map_w
		&& game->map_pos_y > 0 && game->map_pos_y < game->map_h
		&& game->map[game->map_pos_y][game->map_pos_x] != '1')
	{
		if (game->map[game->map_pos_y][game->map_pos_x] == 'Q')
		{
			game->flag_exit = 1;
			break ;
		}
		game->rays.hit_x += game->rays.step_x;
		game->rays.hit_y += game->rays.step_y;
		game->map_pos_x = game->rays.hit_x / (int)TILE;
		game->map_pos_y = game->rays.hit_y / (int)TILE;
	}
}
  • When horizontal and vertical intersections are merged, you have to check the lowest distance between player and wall using Pythagore theorem.
  • Now you know which side of the wall you have to drawn.

Fisheye effect

  • This way will show distortion called "fish-eye".
  • To remove the viewing distortion : correct_dist = distorted_dist * cos(angle);

Sources

cub3d's People

Contributors

bima42 avatar yvanoffp avatar

Watchers

 avatar

Forkers

yvanoffp

cub3d's Issues

Parsing : File part

There is some point to do :

  • File name of map end with .cub
  • Collect infos map
  • Check the validity of those infos
  • Deal with allowed new lines between infos
  • Collect map description
  • Check validity map (walls, player position)

Init: Rearrange map using pixels

Our map need to be modified : one char is a block of 64x64 pixels

I think we have to put color inside each block to prebuild 2D map, have to talk about that (not sure)

Raycasting: Struct

Had to build a ray_struct which contains :

  • double ang;
  • double horizon_x;
  • double vertical_y;
  • double tan;
  • double hit_x and double hit_y;
  • double dist;

And add this struct in our game_struct

We need to init the key struct.

rn when we push A or D while the game is running we get a segfault. might be because the struct holding it is badly init 🗡️

Malloc: organize memory allocation

Some malloc (mlx/texture part) had to be make after parsing when we know map is ok

Btw, those malloc happen after checking path etc. Because, if path are wrong, we dont want malloc for nothing

Parsing structure

Build a parsing structure :

  • Int for player position (int spawn) : if different of 1 = error
  • Int for walls_err : if different of 0 = error
  • Int for valide for path_err : if different of 0 = error
  • Int for id_err (invalide ID) : if different of 0 = error
  • Int for rgb_err (invalide rgb value) : if different of 0 = error

Free main struct.

We should do the destroy func. to destroy and free the main structure (game).
Since we init all datas on 0 or NULL we can protect it pretty ez

Init: try to delete malloc

At this time, all of our structs are malloced

I think we can just declare each struct and give addresses to pointer in our game struct

Check Hooks

Make defines for the keycodes
check how the bindings should be done

Raycasting: Define

To define :

  • FOV : 60.0
  • WALL_RES : 64
  • CUBE or TILE : 64
  • NORTH : 90
  • SOUTH : 270
  • EAST : 0
  • WEST : 180
  • PI : 3.141592

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.