0% encontró este documento útil (0 votos)
2 vistas15 páginas

Raycasting - Fórmulas Simples (ES)

El documento describe las constantes y estructuras necesarias para el motor de raycasting en 3D, incluyendo configuraciones de pantalla, controles del jugador y parámetros de renderizado. Se detallan las estructuras que representan al jugador, los rayos, las texturas y el proceso de dibujar elementos en pantalla. Además, se explican funciones para rotar y mover al jugador, asegurando que las colisiones con paredes sean manejadas correctamente.

Cargado por

angolavibe4
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
2 vistas15 páginas

Raycasting - Fórmulas Simples (ES)

El documento describe las constantes y estructuras necesarias para el motor de raycasting en 3D, incluyendo configuraciones de pantalla, controles del jugador y parámetros de renderizado. Se detallan las estructuras que representan al jugador, los rayos, las texturas y el proceso de dibujar elementos en pantalla. Además, se explican funciones para rotar y mover al jugador, asegurando que las colisiones con paredes sean manejadas correctamente.

Cargado por

angolavibe4
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

/**

* Este archivo contiene todas las definiciones de constantes necesarias para el


* funcionamiento del motor de raycasting en 3D, incluyendo configuraciones de
* pantalla, controles del jugador y parámetros de renderizado.
*
* CONSTANTES DE PANTALLA:
* - WIDTH: Ancho de la ventana en píxeles (1920 píxeles)
* - HEIGHT: Alto de la ventana en píxeles (1080 píxeles)
*
* PARÁMETROS DEL JUEGO:
* - FOV: Campo de visión del jugador (0.90 radianes ≈ 51.5 grados)
* - PLAYER_SPEED: Velocidad de movimiento del jugador (0.1 unidades por frame)
*
* CÓDIGOS DE TECLAS (valores numéricos ASCII/X11):
* Teclas de movimiento:
* - KEY_W (119): Tecla W para mover hacia adelante
* - KEY_S (115): Tecla S para mover hacia atrás
* - KEY_D (100): Tecla D para mover hacia la derecha
* - KEY_A (97): Tecla A para mover hacia la izquierda
*
* Teclas direccionales:
* - KEY_LEFT (65361): Flecha izquierda para rotar a la izquierda
* - KEY_UP (65362): Flecha arriba (funcionalidad adicional)
* - KEY_RIGHT (65363): Flecha derecha para rotar a la derecha
* - KEY_DOWN (65364): Flecha abajo (funcionalidad adicional)
*
* Teclas especiales:
* - KEY_ESC (65307): Tecla Escape para salir del programa
*
* @note Requiere la librería math.h para funciones matemáticas del raycasting
* @note Los valores de las teclas corresponden al sistema de ventanas X11
*/

/**
* @brief Estructura que representa un jugador en el juego de raycasting 3D
*
* Esta estructura contiene toda la información necesaria para definir la posición,
* orientación y campo de visión del jugador en el mundo 3D.
*
* @param pos_x Coordenada X de la posición del jugador en el mapa (tipo double)
* Representa la posición horizontal del jugador en unidades del mapa
*
* @param pos_y Coordenada Y de la posición del jugador en el mapa (tipo double)
* Representa la posición vertical del jugador en unidades del mapa
*
* @param dir_x Componente X del vector de dirección del jugador (tipo double)
* Indica hacia dónde está mirando el jugador en el eje horizontal
* Valores típicos van de -1.0 a 1.0
*
* @param dir_y Componente Y del vector de dirección del jugador (tipo double)
* Indica hacia dónde está mirando el jugador en el eje vertical
* Valores típicos van de -1.0 a 1.0
*
* @param plane_x Componente X del plano de la cámara (tipo double)
* Define el campo de visión horizontal del jugador
* Perpendicular al vector de dirección
*
* @param plane_y Componente Y del plano de la cámara (tipo double)
* Define el campo de visión vertical del jugador
* Perpendicular al vector de dirección
*
* @param pitch Ángulo de inclinación vertical de la cámara (tipo double)
* Permite mirar hacia arriba o hacia abajo
* Valor en radianes, donde 0 es mirar al frente
*
* @note Los vectores dir_x, dir_y forman el vector de dirección del jugador
* @note Los vectores plane_x, plane_y definen el plano de proyección para el raycasting
* @note Esta estructura es fundamental para los cálculos de raycasting en cub3D
*/

/**
* @brief Estructura que contiene todos los datos necesarios para un rayo en el algoritmo de raycasting
*
* Esta estructura almacena toda la información que necesita un rayo individual durante
* el proceso de raycasting para determinar qué paredes son visibles y a qué distancia.
*
* @param camera_x Posición X del rayo en la cámara (coordenada de pantalla normalizada entre -1 y 1)
* @param dir_x Componente X de la dirección del rayo (vector unitario)
* @param dir_y Componente Y de la dirección del rayo (vector unitario)
* @param delta_dist_x Distancia que debe recorrer el rayo para moverse de una línea vertical a la siguiente
* @param delta_dist_y Distancia que debe recorrer el rayo para moverse de una línea horizontal a la siguiente
* @param side_dist_x Distancia desde la posición actual hasta la próxima línea vertical del mapa
* @param side_dist_y Distancia desde la posición actual hasta la próxima línea horizontal del mapa
* @param perp_wall_dist Distancia perpendicular desde el jugador hasta la pared (evita el efecto ojo de pez)
* @param step_x Dirección de avance en X (-1 o +1) hacia la siguiente casilla del mapa
* @param step_y Dirección de avance en Y (-1 o +1) hacia la siguiente casilla del mapa
* @param map_x Coordenada X actual en el mapa (casilla entera)
* @param map_y Coordenada Y actual en el mapa (casilla entera)
* @param side Indica qué lado de la pared fue golpeado (0=vertical Norte/Sur, 1=horizontal Este/Oeste)
* @param line_height Altura en píxeles de la línea de pared que se debe dibujar en pantalla
*
* Proceso paso a paso del raycasting:
* 1. Se calcula camera_x para determinar qué parte de la pantalla corresponde al rayo
* 2. Se establecen dir_x y dir_y como la dirección del rayo desde el jugador
* 3. Se calculan delta_dist_x y delta_dist_y para saber cuánto avanza el rayo entre casillas
* 4. Se determinan step_x, step_y y las distancias iniciales side_dist_x, side_dist_y
* 5. Se ejecuta el algoritmo DDA para encontrar la pared más cercana
* 6. Se actualiza perp_wall_dist con la distancia a la pared encontrada
* 7. Se calcula line_height basándose en perp_wall_dist para el renderizado
*/

/**
* @brief Estructura que almacena toda la información necesaria para manejar texturas en el motor de raycasting
*
* Esta estructura contiene arrays para manejar hasta 4 texturas diferentes (generalmente para las 4 direcciones:
* Norte, Sur, Este, Oeste en un juego estilo laberinto 3D).
*
* Campos de imagen y datos:
* @param img Array de 4 punteros void que almacenan las imágenes de textura cargadas en memoria
* @param data Array de 4 punteros char que contienen los datos de píxeles de cada textura
* @param filename Array de 4 cadenas que guardan los nombres de archivo de cada textura
*
* Propiedades de las texturas:
* @param width Array de 4 enteros con el ancho en píxeles de cada textura
* @param height Array de 4 enteros con la altura en píxeles de cada textura
* @param bpp Array de 4 enteros con los bits por píxel de cada textura
* @param line_size Array de 4 enteros con el tamaño de línea en bytes de cada textura
* @param endian Array de 4 enteros que indica el orden de bytes (big/little endian) de cada textura
*
* Coordenadas y control de renderizado:
* @param x Coordenada X actual en la textura durante el renderizado
* @param y Coordenada Y actual en la textura durante el renderizado
* @param current Índice (0-3) de la textura que se está usando actualmente
*
* Cálculos de mapeo de textura:
* @param step Incremento para avanzar por la textura verticalmente (usado en algoritmos de raycasting)
* @param pos Posición actual en la textura (coordenada flotante para interpolación suave)
*
* Esta estructura es fundamental para el sistema de texturas del raycaster, permitiendo
* mapear correctamente las texturas sobre las paredes del mundo 3D.
*/

/**
* @brief Estructura que define los parámetros necesarios para dibujar una línea vertical en pantalla
*
* Esta estructura almacena toda la información necesaria para renderizar una columna
* de píxeles en la pantalla durante el proceso de raycasting en un motor 3D.
*
* @param start Píxel de inicio donde comenzar a dibujar la línea vertical (coordenada Y)
* @param end Píxel final donde terminar de dibujar la línea vertical (coordenada Y)
* @param colour Color en formato entero que se aplicará a todos los píxeles de la línea
*
* Uso típico:
* 1. Se calcula la altura de la pared proyectada en pantalla
* 2. Se determina el píxel de inicio (start) y final (end) de la línea vertical
* 3. Se asigna el color (colour) correspondiente a la textura de la pared
* 4. Se utiliza esta información para dibujar la columna completa de píxeles
*/

/**
* @brief Estructura principal que contiene todos los datos del juego Cub3D
*
* Esta estructura almacena toda la información necesaria para el funcionamiento
* del juego de raycasting Cub3D, incluyendo ventanas, imágenes, mapas y objetos
* del juego.
*
* @param root Puntero a la instancia principal de GRAPHIC (lib)
* @param win Puntero a la ventana del juego creada con GRAPHIC
* @param screen Puntero a la imagen donde se dibuja todo el contenido visual
* @param img_data Puntero a los datos de píxeles de la imagen (buffer de pantalla)
* @param map Matriz de caracteres que representa el mapa del juego (2D)
* @param map_file Array de caracteres que almacena la ruta del archivo de mapa
* @param bbp Bits por píxel de la imagen (información de formato de color)
* @param endian Orden de bytes de la imagen (little-endian o big-endian)
* @param line_size Tamaño en bytes de cada línea de la imagen
* @param map_width Ancho del mapa en número de celdas
* @param map_height Alto del mapa en número de celdas
* @param player Estructura que contiene toda la información del jugador
* @param ray Estructura que contiene los datos del rayo para el raycasting
* @param draw Estructura con información para dibujar elementos en pantalla
* @param texture Estructura que maneja las texturas de paredes y elementos
*
* Esta estructura actúa como el núcleo central del programa, conectando
* todos los componentes necesarios para renderizar el mundo 3D mediante
* técnicas de raycasting.
*/

/**
* @brief Aplica una rotación 2D a un punto usando una matriz de rotación
*
* Esta función rota un punto (x, y) alrededor del origen por un ángulo dado.
* Utiliza las fórmulas matemáticas de rotación en 2D:
* - nueva_x = x * cos(ángulo) - y * sin(ángulo)
* - nueva_y = x * sin(ángulo) + y * cos(ángulo)
*
* Pasos detallados:
* 1. Guarda el valor original de x en old_x para no perderlo
* 2. Calcula la nueva coordenada x usando cos() y sin():
* - Multiplica x original por cos(angle)
* - Multiplica y original por sin(angle)
* - Resta el segundo resultado del primero
* 3. Calcula la nueva coordenada y usando cos() y sin():
* - Multiplica y original por cos(angle)
* - Multiplica old_x (x original) por sin(angle)
* - Suma ambos resultados
*
* @param x Puntero a la coordenada x del punto a rotar (se modifica)
* @param y Puntero a la coordenada y del punto a rotar (se modifica)
* @param angle Ángulo de rotación en radianes (positivo = antihorario)
*
* @note Funciones matemáticas utilizadas: cos(), sin()
* @note El ángulo debe estar en radianes, no en grados
* @note La rotación se realiza alrededor del origen (0,0)
*/
void rotation_formula(double *x, double *y, double angle)
{
const double old_x = *x;

*x = *x * cos(angle) - *y * sin(angle);
*y = *y * cos(angle) + old_x * sin(angle);
}

/**
* @brief Rota al jugador en el mundo 3D cambiando su dirección y plano de visión
*
* Esta función permite que el jugador gire hacia la izquierda o derecha en el juego.
* Funciona como cuando giras tu cabeza para mirar hacia otro lado.
*
* Pasos que realiza:
* 1. Primero rota el vector de dirección del jugador (hacia donde está mirando)
* usando la función rotation_formula() con la velocidad especificada
* 2. Luego rota el plano de la cámara del jugador (que define su campo de visión)
* usando la misma función rotation_formula() con la misma velocidad
*
* Funciones utilizadas:
* - rotation_formula(): Se llama dos veces para rotar tanto la dirección como el plano
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
* @param speed Velocidad de rotación (positiva = giro a la derecha, negativa = giro a la izquierda)
*
* @note Es importante rotar tanto la dirección como el plano para mantener la coherencia
* de la cámara y evitar distorsiones visuales en el renderizado
*/

/**
* @brief Calcula la nueva posición después de aplicar movimiento en una dirección específica
*
* Esta función implementa la fórmula básica de movimiento en física:
* nueva_posición = posición_actual + (dirección × velocidad)
*
* Pasos detallados que realiza la función:
* 1. Toma la posición actual del objeto (pos)
* 2. Toma la dirección del movimiento (dir) - puede ser positiva o negativa
* 3. Toma la velocidad del movimiento (speed) - qué tan rápido se mueve
* 4. Multiplica la dirección por la velocidad para obtener el desplazamiento
* 5. Suma el desplazamiento a la posición actual
* 6. Devuelve la nueva posición calculada
*
* @param pos Posición actual en el eje (coordenada X o Y)
* @param dir Dirección del movimiento (-1.0 a 1.0, donde -1 es hacia atrás y 1 es hacia adelante)
* @param speed Velocidad del movimiento (unidades por frame o por segundo)
* @return double Nueva posición después del movimiento
*
* Funciones utilizadas:
* - Ninguna función externa es llamada en esta implementación
* - Solo utiliza operaciones matemáticas básicas (multiplicación y suma)
*
* Ejemplo de uso:
* - Si pos=10.0, dir=1.0, speed=2.0 → resultado: 12.0 (se movió 2 unidades hacia adelante)
* - Si pos=10.0, dir=-1.0, speed=2.0 → resultado: 8.0 (se movió 2 unidades hacia atrás)
*/
double movement_formula(double pos, double dir, double speed)
{
return (pos + dir * speed);
}

/**
* @brief Mueve al jugador en el mapa verificando que no colisione con paredes
*
* Esta función calcula la nueva posición del jugador basándose en la velocidad
* y dirección especificadas, y solo actualiza la posición si el destino es válido.
*
* Pasos detallados:
* 1. Declara variables x e y para almacenar la nueva posición calculada
* 2. Verifica el parámetro 'coord' para determinar el tipo de movimiento:
* - Si coord es 'x': usa los vectores del plano (plane_x, plane_y) para movimiento lateral
* - Si coord es cualquier otro valor: usa los vectores de dirección (dir_x, dir_y) para movimiento frontal
* 3. Calcula la nueva posición x llamando a movement_formula() con:
* - Posición actual en x (pos_x)
* - Vector correspondiente en x (plane_x o dir_x según el caso)
* - Velocidad de movimiento (speed)
* 4. Calcula la nueva posición y llamando a movement_formula() con:
* - Posición actual en y (pos_y)
* - Vector correspondiente en y (plane_y o dir_y según el caso)
* - Velocidad de movimiento (speed)
* 5. Verifica que la nueva posición sea válida:
* - Convierte las coordenadas x e y a enteros para acceder al mapa
* - Comprueba si la celda del mapa en esa posición contiene '0' (espacio libre)
* 6. Si la posición es válida (no hay pared):
* - Actualiza pos_x con el nuevo valor calculado
* - Actualiza pos_y con el nuevo valor calculado
*
* Funciones utilizadas:
* - movement_formula(): Calcula la nueva coordenada basándose en posición actual, vector de dirección y velocidad
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
* @param speed Velocidad del movimiento (puede ser positiva o negativa)
* @param coord Carácter que indica el tipo de movimiento ('x' para lateral, otro valor para frontal)
*/

/**
* Extrae el contenido del mapa desde un archivo y lo almacena en la estructura de datos.
*
* Esta función realiza los siguientes pasos:
* 1. Abre el archivo "[Link]" en modo de solo lectura usando open()
* 2. Lee todo el contenido del archivo y lo guarda en data->map_file usando read()
* 3. Encuentra el final del texto leído con strlen() y reemplaza el último
* carácter (generalmente un salto de línea) con un terminador nulo '\0'
* 4. Cierra el archivo usando close() para liberar recursos
*
* @param data Puntero a la estructura t_data que contiene el buffer map_file
* donde se almacenará el contenido del archivo del mapa
*
* Funciones utilizadas:
* - open(): Abre el archivo "[Link]"
* - read(): Lee el contenido del archivo hacia el buffer
* - strlen(): Calcula la longitud de la cadena leída
* - close(): Cierra el descriptor de archivo
*/

/**
* @brief Inicializa la posición y orientación del jugador en el mapa
*
* Esta función establece la posición inicial del jugador y configura su campo de visión
* para el sistema de raycasting. Es como colocar al jugador en el centro de una casilla
* del mapa y decirle hacia dónde debe mirar.
*
* Pasos detallados:
* 1. Coloca al jugador en el centro de la casilla (x, y) sumando 0.5 a cada coordenada
* - data->player.pos_x = x + 0.5: Posición horizontal del jugador
* - data->player.pos_y = y + 0.5: Posición vertical del jugador
*
* 2. Establece la dirección inicial hacia la que mira el jugador (hacia arriba)
* - data->player.dir_x = 0: Sin movimiento horizontal en la dirección
* - data->player.dir_y = -1: Mirando hacia arriba (coordenadas invertidas)
*
* 3. Configura el plano de la cámara para el campo de visión (FOV)
* - data->player.plane_x = FOV: Ancho del campo de visión horizontal
* - data->player.plane_y = 0: Sin inclinación vertical del campo de visión
*
* 4. Limpia la casilla inicial del mapa marcándola como espacio vacío
* - data->map[y][x] = '0': Convierte la posición inicial en suelo transitable
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
* @param x Coordenada horizontal (columna) donde se colocará el jugador
* @param y Coordenada vertical (fila) donde se colocará el jugador
*
* @note Esta función no utiliza otras funciones, solo realiza asignaciones directas
* @note FOV debe estar definido como una constante antes de usar esta función
*/

/**
* @brief Busca la posición del jugador en el mapa y establece su posición inicial
*
* Esta función encuentra al jugador (representado por 'P') en el mapa del juego
* y configura su posición de inicio. Realiza los siguientes pasos:
*
* 1. Divide el archivo del mapa en líneas usando split() con '\n' como separador
* 2. Inicializa data->map_height a 0 para contar las filas
* 3. Cuenta el número total de filas del mapa incrementando data->map_height
* 4. Recorre cada fila del mapa (y va de 0 a data->map_height-1):
* - Inicializa x a -1 para recorrer las columnas
* - Calcula el ancho de la fila actual usando strlen() y lo guarda en data->map_width
* - Recorre cada columna de la fila actual (x va de 0 a data->map_width-1):
* - Si encuentra el carácter 'P' (que representa al jugador):
* - Llama a start_position() pasando los datos del juego y las coordenadas x,y
* - Termina la función con return
*
* @param data Puntero a la estructura principal que contiene:
* - map_file: archivo del mapa en formato string
* - map: array de strings (filas del mapa) después de split()
* - map_height: altura del mapa (número de filas)
* - map_width: ancho de la fila actual
*
* @note La función asume que existe exactamente un carácter 'P' en el mapa
* @note Utiliza las funciones: split(), strlen(), start_position()
*/
void find_player(t_data *data)
{
int x;
int y;

data->map = split(data->map_file, '\n');


data->map_height = 0;
while (data->map[data->map_height])
data->map_height++;
y = -1;
while (++y < data->map_height)
{
x = -1;
data->map_width = (int)strlen(data->map[y]);
while (++x < data->map_width)
{
if (data->map[y][x] == 'P')
return (start_position(data, x, y));
}
}
}

/**
* @brief Coloca un píxel de color específico en una posición determinada de la imagen
*
* Esta función escribe directamente en la memoria de la imagen para cambiar el color
* de un píxel individual. Es como pintar un punto muy pequeño en un lienzo digital.
*
* Pasos detallados:
* 1. Calcula la posición exacta en memoria donde está el píxel
* - Multiplica 'y' por 'line_size' para encontrar la fila correcta
* - Multiplica 'x' por 4 para encontrar la columna (cada píxel usa 4 bytes)
* - Suma ambos valores para obtener la posición final
* 2. Suma esta posición a 'img_data' (que apunta al inicio de la imagen)
* 3. Convierte el resultado a un puntero de entero sin signo (unsigned int *)
* 4. Asigna el valor del color a esa posición de memoria usando el operador *
*
* @param data Estructura que contiene la información de la imagen (img_data, line_size)
* @param x Coordenada horizontal del píxel (columna)
* @param y Coordenada vertical del píxel (fila)
* @param colour Color que se va a asignar al píxel (valor entero que representa ARGB)
*
* @note Esta función no verifica si las coordenadas están dentro de los límites de la imagen
* @note Cada píxel ocupa 4 bytes en memoria (formato ARGB de 32 bits)
*/
void pixel_put_formula(t_data *data, int x, int y, int colour)
{
*(unsigned int *)(data->img_data + (y * data->line_size + x * 4)) = colour;
}

/**
* @brief Establece el color de un rayo basándose en su dirección y coordenada
*
* Esta función determina qué color asignar a un rayo dependiendo de dos factores:
* la coordenada que se está evaluando (x o y) y la dirección del paso del rayo
* (positivo o negativo).
*
* Pasos que realiza la función:
* 1. Verifica si la coordenada recibida es 'x'
* 2. Si es coordenada 'x':
* - Si ray_step es positivo (> 0): asigna color rojo (0xFF0000)
* - Si ray_step es negativo o cero: asigna color magenta (0xFF00FF)
* 3. Si NO es coordenada 'x' (asume que es 'y'):
* - Si ray_step es positivo (> 0): asigna color azul (0x0000FF)
* - Si ray_step es negativo o cero: asigna color amarillo (0xFFFF00)
* 4. El color se asigna directamente al valor apuntado por el puntero colour
*
* @param ray_step Valor entero que indica la dirección del paso del rayo
* (positivo = una dirección, negativo/cero = dirección opuesta)
* @param colour Puntero al entero donde se almacenará el color calculado
* @param coord Carácter que indica la coordenada a evaluar ('x' para eje X,
* cualquier otro valor se trata como eje Y)
*
* @note Los colores están en formato hexadecimal RGB:
* - 0xFF0000 = Rojo puro
* - 0xFF00FF = Magenta
* - 0x0000FF = Azul puro
* - 0xFFFF00 = Amarillo
*
* @note Esta función no utiliza ninguna función externa, solo operaciones
* de comparación y asignación básicas
*/
void colour_set_formula(int ray_step, int *colour, char coord)
{
if (coord == 'x')
{
if (ray_step > 0)
*colour = 0xFF0000;
else
*colour = 0xFF00FF;
}
else
{
if (ray_step > 0)
*colour = 0x0000FF;
else
*colour = 0xFFFF00;
}
}

/**
* @brief Dibuja una columna vertical de la escena en la pantalla (como una línea de píxeles)
*
* Esta función es como pintar una línea vertical en un dibujo. Imagina que tienes una hoja
* de papel y quieres dibujar una línea desde arriba hasta abajo, pero con diferentes colores
* en diferentes partes.
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
* @param x La posición horizontal (columna) donde vamos a dibujar la línea vertical
*
* Pasos que hace la función:
* 1. Prepara un contador 'y' en -1 para contar desde arriba hacia abajo
* 2. Llama a colour_set_formula() para decidir qué color usar según el paso en Y
* 3. Si el rayo tocó una pared vertical (side == 0), llama otra vez a colour_set_formula()
* para ajustar el color según el paso en X
* 4. Recorre todos los píxeles de arriba a abajo (desde y=0 hasta HEIGHT):
* - Si estamos arriba de la pared (y < data->[Link]):
* Llama a pixel_put_formula() para pintar el cielo de color celeste (0x00FFFF)
* - Si estamos en la zona de la pared (entre start y end):
* Llama a pixel_put_formula() para pintar la pared del color calculado
* - Si estamos abajo de la pared (y > data->[Link]):
* Llama a pixel_put_formula() para pintar el suelo de color verde (0x228B22)
*
* Funciones utilizadas:
* - colour_set_formula(): Calcula y establece el color de la pared
* - pixel_put_formula(): Pinta un píxel individual en la pantalla
*/
void draw_scene_formula(t_data *data, int x)
{
int y;

y = -1;
colour_set_formula(data->ray.step_y, &data->[Link], 'y');
if (data->[Link] == 0)
colour_set_formula(data->ray.step_x, &data->[Link], 'x');
while (++y < HEIGHT)
{
if (y < data->[Link])
pixel_put_formula(data, x, y, 0x00FFFF);
else if (y >= data->[Link] && y <= data->[Link])
pixel_put_formula(data, x, y, data->[Link]);
else
pixel_put_formula(data, x, y, 0x228B22);
}
}

/**
* @brief Actualiza la distancia lateral y la posición en el mapa durante el algoritmo DDA
*
* Esta función realiza un paso del algoritmo DDA (Digital Differential Analyzer)
* utilizado en raycasting. Actualiza tanto la distancia lateral acumulada como
* la coordenada actual en el mapa.
*
* Pasos detallados:
* 1. Suma el valor de delta_dist a la distancia lateral actual (*side_dist)
* - Esto representa avanzar un paso completo en la dirección del rayo
* 2. Suma el valor de ray_step a la coordenada del mapa (*map_dir)
* - Esto mueve la posición actual en el mapa una casilla en la dirección correcta
* - ray_step puede ser +1 (avanzar) o -1 (retroceder) según la dirección del rayo
*
* @param side_dist Puntero a la distancia lateral acumulada desde el punto de origen
* @param delta_dist Distancia que debe recorrer el rayo para cruzar una casilla completa
* @param map_dir Puntero a la coordenada actual en el mapa (X o Y)
* @param ray_step Dirección del paso: +1 para avanzar, -1 para retroceder
*
* @note Esta función se llama repetidamente hasta que el rayo encuentre una pared
* @note No se usan funciones externas en esta implementación
*/
void step_formula(double *side_dist, double delta_dist, int *map_dir,
int ray_step)
{
*side_dist += delta_dist;
*map_dir += ray_step;
}

/**
* @brief Calcula la distancia desde la cámara hasta una pared usando la fórmula DDA
*
* Esta función implementa la fórmula matemática para calcular cuánta distancia debe
* recorrer un rayo desde la posición de la cámara hasta tocar una pared del mapa.
*
* Pasos detallados:
* 1. Toma la posición de la pared en el mapa (map_dir)
* 2. Resta la posición actual de la cámara (camera_pos)
* 3. Ajusta según la dirección del paso del rayo:
* - Si ray_step es 1 (avanza hacia adelante): suma 0 (porque (1-1)/2 = 0)
* - Si ray_step es -1 (retrocede): suma 1 (porque (1-(-1))/2 = 1)
* 4. Divide todo entre la dirección del rayo (ray_dir) para normalizar
* 5. El resultado es la distancia perpendicular hasta la pared
*
* Esta fórmula es parte del algoritmo DDA (Digital Differential Analyzer) que se
* usa en raycasting para detectar colisiones con paredes de forma eficiente.
*
* @param map_dir Coordenada de la pared en el mapa (entero)
* @param camera_pos Posición actual de la cámara (decimal)
* @param ray_step Dirección del paso del rayo (-1 o 1)
* @param ray_dir Dirección del vector del rayo (decimal)
* @return Distancia desde la cámara hasta la pared
*
* Funciones utilizadas: Ninguna (solo operaciones matemáticas básicas)
*/
double wall_distance_formula(int map_dir, double camera_pos, int ray_step,
double ray_dir)
{
return ((map_dir - camera_pos + (1 - ray_step) / 2) / ray_dir);
}

/**
* @brief Calcula la altura en píxeles que debe tener una línea vertical en la pantalla
* para representar una pared en el motor de raycasting.
*
* @details Esta función implementa la fórmula básica del raycasting para determinar
* qué tan alta debe dibujarse una pared en la pantalla:
*
* Paso 1: Toma la altura total de la pantalla (screen_height)
* Paso 2: Divide esta altura por la distancia perpendicular a la pared (perp_wall)
* Paso 3: Convierte el resultado a entero para obtener píxeles exactos
*
* La lógica es: mientras más cerca esté la pared (perp_wall más pequeño),
* más alta se verá en pantalla. Mientras más lejos esté (perp_wall más grande),
* más pequeña se verá.
*
* Funciones utilizadas:
* - (int): conversión explícita a tipo entero
*
* @param screen_height Altura total de la pantalla en píxeles
* @param perp_wall Distancia perpendicular desde el jugador hasta la pared
* @return int Altura en píxeles que debe tener la línea de la pared en pantalla
*/
int ray_line_height_formula(int screen_height, double perp_wall)
{
return ((int)(screen_height / perp_wall));
}

/**
* @brief Calcula la posición de inicio vertical para dibujar una línea de rayo en la pantalla
*
* Esta función determina dónde debe empezar a dibujarse una línea vertical que representa
* una pared en el motor de raycasting. Es como decidir desde qué altura de la pantalla
* empezar a pintar una pared.
*
* Pasos detallados:
* 1. Toma la altura de la línea del rayo (ray_line_height) y la divide entre 2
* 2. Cambia el signo del resultado (lo hace negativo)
* 3. Suma la mitad de la altura de la pantalla (screen_height / 2) para centrar
* 4. Añade el valor de pitch (inclinación de la cámara hacia arriba o abajo)
* 5. Usa fmax() para asegurar que el resultado nunca sea menor que 0
*
* @param ray_line_height Altura en píxeles de la línea que representa la pared
* @param screen_height Altura total de la pantalla en píxeles
* @param pitch Valor de inclinación de la cámara (positivo = mirar hacia arriba)
*
* @return Posición Y donde debe empezar a dibujarse la línea (nunca menor que 0)
*
* @note Utiliza la función fmax() para evitar valores negativos
*/
double draw_start_formula(int ray_line_height, int screen_height, double pitch)
{
return (fmax(0, (-ray_line_height / 2) + (screen_height / 2) + pitch));
}

/**
* @brief Calcula la posición del píxel donde termina de dibujarse una línea vertical en el raycast
*
* Esta función determina dónde debe dejar de dibujarse una pared en la pantalla.
* Funciona paso a paso así:
*
* 1. Primero toma la altura de la línea del rayo (ray_line_height) y la divide por 2
* para encontrar la mitad de la altura de la pared
*
* 2. Luego toma la altura de la pantalla (screen_height) y la divide por 2
* para encontrar el centro vertical de la pantalla
*
* 3. Suma estos dos valores junto con el pitch (inclinación de la cámara)
* para obtener la posición final donde debe terminar el dibujo
*
* 4. Finalmente usa la función fmin() para asegurarse de que el resultado
* no sea mayor que (screen_height - 1), evitando dibujar fuera de la pantalla
*
* @param ray_line_height Altura en píxeles de la línea del rayo proyectada
* @param screen_height Altura total de la pantalla en píxeles
* @param pitch Valor de inclinación vertical de la cámara
* @return Posición del píxel donde debe terminar el dibujo de la pared (coordenada Y)
*
* @note Usa la función fmin() para limitar el valor máximo
*/
double draw_end_formula(int ray_line_height, int screen_height, double pitch)
{
return (fmin(screen_height - 1, (ray_line_height / 2) + (screen_height / 2)
+ pitch));
}

/**
* @brief Calcula el paso del rayo y la distancia lateral inicial para el algoritmo DDA
*
* Esta función determina en qué dirección debe moverse el rayo (hacia adelante o hacia atrás)
* y calcula la distancia desde la posición actual de la cámara hasta el siguiente borde de celda
* en el mapa.
*
* Pasos detallados:
* 1. Revisa si la dirección del rayo es negativa (ray_dir < 0)
* 2. Si es negativa (va hacia atrás):
* - Calcula la distancia desde la posición de la cámara hasta el borde izquierdo/inferior
* de la celda actual usando: (camera_pos - ray_map_coord) * ray_delta_dist
* - Almacena esta distancia en ray_side_dist
* - Retorna -1 para indicar que el paso es hacia atrás
* 3. Si es positiva (va hacia adelante):
* - Calcula la distancia desde la posición de la cámara hasta el borde derecho/superior
* de la celda actual usando: (ray_map_coord + 1.0 - camera_pos) * ray_delta_dist
* - Almacena esta distancia en ray_side_dist
* - Retorna 1 para indicar que el paso es hacia adelante
*
* @param ray_dir Dirección del rayo en el eje correspondiente (X o Y)
* @param ray_side_dist Puntero donde se almacenará la distancia lateral calculada
* @param ray_delta_dist Distancia que el rayo debe recorrer para cruzar una celda completa
* @param camera_pos Posición actual de la cámara en el eje correspondiente
* @param ray_map_coord Coordenada entera del mapa donde está la cámara
*
* @return -1 si el rayo va en dirección negativa, 1 si va en dirección positiva
*
* @note Esta función es parte del algoritmo DDA (Digital Differential Analyzer)
* usado en raycasting para determinar intersecciones con paredes
*/
int set_ray_step_and_side_dist_formula(double ray_dir, double *ray_side_dist,
double ray_delta_dist, double camera_pos, int ray_map_coord)
{
if (ray_dir < 0)
{
*ray_side_dist = (camera_pos - ray_map_coord) * ray_delta_dist;
return (-1);
}
*ray_side_dist = (ray_map_coord + 1.0 - camera_pos) * ray_delta_dist;
return (1);
}

/**
* @brief Determina el lado del rayo que debe avanzar en el algoritmo DDA
*
* Esta función compara las distancias laterales del rayo en X e Y para decidir
* en qué dirección debe dar el siguiente paso el algoritmo DDA.
*
* @param ray_side_dist_x Distancia lateral del rayo en el eje X
* @param ray_side_dist_y Distancia lateral del rayo en el eje Y
* @return int 1 si debe avanzar en Y (ray_side_dist_x >= ray_side_dist_y),
* 0 si debe avanzar en X (ray_side_dist_x < ray_side_dist_y)
*/

/**
* @brief Verifica si el rayo ha alcanzado un punto de colisión
*
* Esta función comprueba si el rayo ha salido de los límites del mapa o
* ha encontrado una pared (representada por '1' en el mapa).
*
* @param ray_map_x Posición X actual del rayo en el mapa
* @param ray_map_y Posición Y actual del rayo en el mapa
* @param map_width Ancho total del mapa
* @param map_height Alto total del mapa
* @param map Matriz 2D que representa el mapa del juego
* @return int 1 si hay colisión (fuera de límites o pared encontrada),
* 0 si puede continuar avanzando
*/

/**
* @brief Algoritmo DDA (Digital Differential Analyzer) para raycasting
*
* Esta función implementa el algoritmo DDA que hace avanzar un rayo paso a paso
* por el mapa hasta que encuentra una pared o sale de los límites. Es el corazón
* del sistema de raycasting para renderizado 3D.
*
* Pasos detallados:
* 1. Entra en un bucle que continúa mientras no haya colisión
* 2. Llama a ray_hit_point_condition_formula() para verificar si hay colisión
* 3. Si no hay colisión, llama a ray_side_condition_formula() para decidir dirección
* 4. Si ray_side_condition_formula() devuelve 1 (avanzar en Y):
* - Llama a step_formula() con parámetros del eje Y
* - Actualiza side_dist_y, map_y usando delta_dist_y y step_y
* 5. Si ray_side_condition_formula() devuelve 0 (avanzar en X):
* - Llama a step_formula() con parámetros del eje X
* - Actualiza side_dist_x, map_x usando delta_dist_x y step_x
* 6. Repite hasta encontrar una pared o salir del mapa
*
* @param data Estructura principal que contiene todos los datos del rayo,
* mapa y configuración necesarios para el raycasting
*/
int ray_side_condition_formula(double ray_side_dist_x, double ray_side_dist_y)
{
return (!(ray_side_dist_x < ray_side_dist_y));
}

int ray_hit_point_condition_formula(int ray_map_x, int ray_map_y, int map_width,


int map_height, char **map)
{
return ((ray_map_x < 0 || ray_map_x >= map_width || ray_map_y < 0
|| ray_map_y >= map_height || map[ray_map_y][ray_map_x] == '1'));
}

void dda(t_data *data)


{
while (!ray_hit_point_condition_formula(data->ray.map_x, data->ray.map_y,
data->map_width, data->map_height, data->map))
{
data->[Link] = ray_side_condition_formula(data->ray.side_dist_x,
data->ray.side_dist_y);
if (data->[Link])
step_formula(&data->ray.side_dist_y, data->ray.delta_dist_y,
&data->ray.map_y, data->ray.step_y);
else
step_formula(&data->ray.side_dist_x, data->ray.delta_dist_x,
&data->ray.map_x, data->ray.step_x);
}
}

/**
* @brief Calcula la distancia perpendicular desde el jugador hasta la pared detectada
*
* Esta función determina qué tipo de pared fue golpeada por el rayo (vertical u horizontal)
* y calcula la distancia perpendicular correcta para evitar el efecto "ojo de pez".
*
* Pasos detallados:
* 1. Verifica si data->[Link] es igual a 0 (pared vertical) o 1 (pared horizontal)
* 2. Si side == 0 (pared vertical):
* - Usa la posición X del mapa (data->ray.map_x)
* - Usa la posición X del jugador (data->player.pos_x)
* - Usa el paso X del rayo (data->ray.step_x)
* - Usa la dirección X del rayo (data->ray.dir_x)
* - Llama a wall_distance_formula() con estos parámetros
* 3. Si side == 1 (pared horizontal):
* - Usa la posición Y del mapa (data->ray.map_y)
* - Usa la posición Y del jugador (data->player.pos_y)
* - Usa el paso Y del rayo (data->ray.step_y)
* - Usa la dirección Y del rayo (data->ray.dir_y)
* - Llama a wall_distance_formula() con estos parámetros
* 4. Guarda el resultado en data->ray.perp_wall_dist
*
* Funciones utilizadas:
* - wall_distance_formula()
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
*/

/**
* @brief Calcula la altura de la línea vertical que representa la pared en la pantalla
*
* Esta función determina qué tan alta debe dibujarse la pared en la pantalla
* basándose en la distancia perpendicular calculada anteriormente.
*
* Pasos detallados:
* 1. Toma la altura de la pantalla (HEIGHT)
* 2. Toma la distancia perpendicular a la pared (data->ray.perp_wall_dist)
* 3. Llama a ray_line_height_formula() con estos dos parámetros
* 4. La función calcula: HEIGHT / data->ray.perp_wall_dist
* 5. Guarda el resultado en data->ray.line_height
*
* Nota: Mientras más lejos esté la pared, menor será line_height (pared más pequeña)
* Mientras más cerca esté la pared, mayor será line_height (pared más grande)
*
* Funciones utilizadas:
* - ray_line_height_formula()
*
* @param data Puntero a la estructura principal que contiene toda la información del juego
*/
void wall_distance(t_data *data)
{
if (data->[Link] == 0)
data->ray.perp_wall_dist = wall_distance_formula(data->ray.map_x,
data->player.pos_x, data->ray.step_x, data->ray.dir_x);
else
data->ray.perp_wall_dist = wall_distance_formula(data->ray.map_y,
data->player.pos_y, data->ray.step_y, data->ray.dir_y);
}

void ray_line_height(t_data *data)


{
data->ray.line_height = ray_line_height_formula(HEIGHT,
data->ray.perp_wall_dist);
}

/**
* @brief Calcula y establece los puntos de inicio y fin para dibujar una línea vertical en la pantalla
*
* Esta función se encarga de determinar dónde debe empezar y terminar el dibujo de una línea
* vertical que representa una pared en el renderizado 3D. Es como decidir desde qué pixel
* de arriba hasta qué pixel de abajo vamos a pintar la pared en la pantalla.
*
* Pasos que realiza la función:
* 1. Llama a la función draw_start_formula() para calcular el punto de inicio del dibujo
* - Le pasa la altura de la línea (data->ray.line_height)
* - Le pasa la altura total de la pantalla (HEIGHT)
* - Le pasa la inclinación de la cámara del jugador (data->[Link])
* - El resultado se guarda en data->[Link]
*
* 2. Llama a la función draw_end_formula() para calcular el punto final del dibujo
* - Le pasa los mismos parámetros que a la función anterior
* - El resultado se guarda en data->[Link]
*
* @param data Puntero a la estructura principal que contiene toda la información del juego:
* - data->ray.line_height: altura calculada de la línea a dibujar
* - data->[Link]: inclinación vertical de la vista del jugador
* - data->[Link]: donde se guardará el pixel de inicio (se modifica)
* - data->[Link]: donde se guardará el pixel final (se modifica)
*
* @note Esta función no devuelve nada, pero modifica los valores de [Link] y [Link]
* dentro de la estructura data
*/

void set_ray_direction_formula(double *ray_dir, double player_dir,


double player_plane, double ray_camera_x, int *ray_map_coord,
double player_pos, double *ray_delta_dist)
{
*ray_dir = player_dir + player_plane * ray_camera_x;
*ray_map_coord = (int)player_pos;
if (*ray_dir == 0)
*ray_delta_dist = 1e30;
else
*ray_delta_dist = fabs(1 / *ray_dir);
}

/**
* @brief Establece la dirección del rayo para el raycasting
*
* Esta función configura la dirección del rayo que se va a lanzar desde la posición
* del jugador. Es como si fuéramos un niño con una linterna apuntando en diferentes
* direcciones para ver qué hay ahí.
*
* Pasos detallados:
* 1. Primero llama a set_ray_direction_formula() para calcular la dirección X del rayo
* - Usa la dirección del jugador en X (data->player.dir_x)
* - Usa el plano de la cámara en X (data->player.plane_x)
* - Usa la posición de la cámara (data->ray.camera_x)
* - Calcula en qué casilla del mapa está en X (data->ray.map_x)
* - Usa la posición actual del jugador en X (data->player.pos_x)
* - Calcula la distancia entre rayos en X (data->ray.delta_dist_x)
*
* 2. Después llama a set_ray_direction_formula() otra vez para calcular la dirección Y del rayo
* - Usa la dirección del jugador en Y (data->player.dir_y)
* - Usa el plano de la cámara en Y (data->player.plane_y)
* - Usa la misma posición de cámara (data->ray.camera_x)
* - Calcula en qué casilla del mapa está en Y (data->ray.map_y)
* - Usa la posición actual del jugador en Y (data->player.pos_y)
* - Calcula la distancia entre rayos en Y (data->ray.delta_dist_y)
*
* @param data Puntero a la estructura principal que contiene toda la información
* del juego (jugador, rayo, mapa, etc.)
*
* @note Esta función prepara todo lo necesario para que después podamos lanzar
* el rayo y calcular qué paredes toca
*/
/**
* DOCUMENTACIÓN DE FUNCIONES DE TEXTURIZADO PARA RAYCASTING
*
* texture_selection_formula - Selecciona qué textura usar según la dirección del rayo
* @ray_step: Dirección del paso del rayo (positivo o negativo)
* @coord: Coordenada que se está evaluando ('x' o 'y')
* @return: Índice de la textura a usar (0-3)
*
* Paso a paso:
* 1. Si estamos evaluando la coordenada 'x':
* - Si ray_step es positivo (movimiento hacia la derecha): devuelve textura 2
* - Si ray_step es negativo (movimiento hacia la izquierda): devuelve textura 3
* 2. Si estamos evaluando la coordenada 'y':
* - Si ray_step es positivo (movimiento hacia abajo): devuelve textura 1
* - Si ray_step es negativo (movimiento hacia arriba): devuelve textura 0
*
* texture_coordinate_formula - Calcula las coordenadas de textura para mapear en la pared
* @data: Estructura principal con todos los datos del juego
* @wall_pos: Posición exacta donde el rayo golpea la pared
* @texture_index: Índice de la textura seleccionada
*
* Paso a paso:
* 1. Calcula la coordenada X de la textura multiplicando wall_pos por el ancho de la textura
* 2. Si el rayo viene del lado correcto, invierte la coordenada X para evitar efecto espejo
* 3. Calcula el paso de textura ([Link]) dividiendo la altura de textura entre la altura de línea
* 4. Calcula la posición inicial de textura considerando el centro de la pantalla
*
* texture_set_formula - Configura todos los parámetros de textura para un rayo
* @ray_step: Dirección del paso del rayo
* @colour: Puntero al color que se modificará
* @coord: Coordenada que se está evaluando
* @data: Estructura principal con todos los datos
*
* Paso a paso:
* 1. Llama a texture_selection_formula para obtener el índice de textura correcto
* 2. Guarda el índice de textura actual en data->[Link]
* 3. Calcula wall_pos (posición en la pared):
* - Si es lado 0: usa posición Y del jugador + distancia * dirección Y del rayo
* - Si es lado 1: usa posición X del jugador + distancia * dirección X del rayo
* 4. Obtiene solo la parte decimal de wall_pos usando floor()
* 5. Llama a texture_coordinate_formula para calcular coordenadas de textura
* 6. Establece el color base como blanco (0xFFFFFF)
*
* texture_pixel_formula - Obtiene el color de un píxel específico de la textura
* @data: Estructura principal con datos de texturas
* @texture_index: Índice de la textura a consultar
* @tex_x: Coordenada X en la textura
* @tex_y: Coordenada Y en la textura
* @return: Color del píxel en formato entero
*
* Paso a paso:
* 1. Verifica que las coordenadas estén dentro de los límites de la textura
* 2. Si están fuera de límites: devuelve color magenta (0xFF00FF) como error
* 3. Si están dentro: calcula la posición exacta en la memoria de la textura
* 4. Devuelve el color del píxel usando aritmética de punteros
*
* draw_scene_with_texture_formula - Dibuja una columna completa de la escena con texturas
* @data: Estructura principal con todos los datos
* @x: Coordenada X de la columna a dibujar
*
* Paso a paso:
* 1. Inicializa variable y en -1 para el bucle
* 2. Configura la textura para el lado Y llamando a texture_set_formula
* 3. Si el rayo golpeó el lado 0, también configura textura para lado X
* 4. Inicia bucle para cada píxel Y de la columna:
* a. Si Y está antes del inicio de la pared: dibuja cielo (color 0x87CEEB) con pixel_put_formula
* b. Si Y está en la pared (entre start y end):
* - Calcula coordenada Y de textura usando máscara bit a bit
* - Avanza la posición de textura
* - Obtiene color del píxel con texture_pixel_formula
* - Dibuja el píxel con pixel_put_formula
* c. Si Y está después del final de la pared: dibuja suelo (color 0x8FBC8F) con pixel_put_formula
*
* Funciones utilizadas:
* - texture_selection_formula: Para seleccionar textura correcta
* - texture_coordinate_formula: Para calcular coordenadas de textura
* - texture_set_formula: Para configurar parámetros de textura
* - texture_pixel_formula: Para obtener color de píxel de textura
* - pixel_put_formula: Para dibujar píxeles en pantalla
* - floor(): Para obtener parte decimal de posición en pared
*/
int texture_selection_formula(int ray_step, char coord)
{
if (coord == 'x')
{
if (ray_step > 0)
return (2);
return (3);
}
if (ray_step > 0)
return (1);
return (0);
}

void texture_coordinate_formula(t_data *data, double wall_pos,


int texture_index)
{
data->texture.x = (int)(wall_pos
* (double)data->[Link][texture_index]);
if ((data->[Link] == 0 && data->ray.dir_x > 0) || (data->[Link] == 1
&& data->ray.dir_y < 0))
data->texture.x = data->[Link][texture_index] - data->texture.x
- 1;
data->[Link] = 1.0 * data->[Link][texture_index]
/ data->ray.line_height;
data->[Link] = (data->[Link] - HEIGHT / 2 + data->ray.line_height
/ 2) * data->[Link];
}

void texture_set_formula(int ray_step, int *colour, char coord, t_data *data)


{
double wall_pos;
int texture_index;

texture_index = texture_selection_formula(ray_step, coord);


data->[Link] = texture_index;
if (data->[Link] == 0)
wall_pos = data->player.pos_y + data->ray.perp_wall_dist
* data->ray.dir_y;
else
wall_pos = data->player.pos_x + data->ray.perp_wall_dist
* data->ray.dir_x;
wall_pos -= floor(wall_pos);
texture_coordinate_formula(data, wall_pos, texture_index);
*colour = 0xFFFFFF;
}

int texture_pixel_formula(t_data *data, int texture_index, int tex_x, int tex_y)


{
if (tex_x < 0 || tex_x >= data->[Link][texture_index] || tex_y < 0
|| tex_y >= data->[Link][texture_index])
return (0xFF00FF);
return (*(int *)(data->[Link][texture_index] + (tex_y
* data->texture.line_size[texture_index] + tex_x * 4)));
}

void draw_scene_with_texture_formula(t_data *data, int x)


{
int y;
int color;

y = -1;
texture_set_formula(data->ray.step_y, &data->[Link], 'y', data);
if (data->[Link] == 0)
texture_set_formula(data->ray.step_x, &data->[Link], 'x', data);
while (++y < HEIGHT)
{
if (y < data->[Link])
pixel_put_formula(data, x, y, 0x87CEEB);
else if (y >= data->[Link] && y <= data->[Link])
{
data->texture.y = (int)data->[Link] & (data->[Link][data->[Link]]
- 1);
data->[Link] += data->[Link];
color = texture_pixel_formula(data, data->[Link],
data->texture.x, data->texture.y);
pixel_put_formula(data, x, y, color);
}
else
pixel_put_formula(data, x, y, 0x8FBC8F);
}
}

/**
* @brief Carga las texturas necesarias para el renderizado de paredes en el motor de raycasting.
*
* Esta función inicializa y carga cuatro texturas desde archivos XPM que serán utilizadas
* para mapear las diferentes caras de las paredes (Norte, Sur, Este, Oeste) durante el
* proceso de raycasting.
*
* Proceso detallado:
* 1. Asigna el nombre del archivo de textura "texture_file.xpm" a los cuatro slots de texturas
* 2. Inicializa el contador del bucle en -1
* 3. Para cada una de las 4 texturas:
* - Carga la imagen desde el archivo XPM usando GRAPHIC_xpm_file_to_image()
* - Obtiene el puntero a los datos de la imagen usando GRAPHIC_get_data_addr()
* - Almacena las propiedades de cada textura (ancho, alto, bits por píxel, tamaño de línea, endianness)
*
* Funciones utilizadas:
* - GRAPHIC_xpm_file_to_image(): Carga una imagen XPM desde archivo y devuelve un puntero a la imagen
* - GRAPHIC_get_data_addr(): Obtiene la dirección de los datos de la imagen y sus propiedades
*
* @param data Puntero a la estructura principal que contiene todos los datos del programa,
* incluyendo la estructura de texturas y el contexto gráfico root
*
* @note Actualmente todas las texturas apuntan al mismo archivo "texture_file.xpm"
* @note Esta función debe ser llamada después de inicializar el contexto gráfico
*/

/**
* @brief Ejecuta el bucle principal de raycasting para renderizar la escena 3D
*
* Esta función implementa el algoritmo de raycasting completo, procesando cada
* columna de píxeles de la pantalla para crear la vista en primera persona.
* Realiza los siguientes pasos detallados:
*
* 1. Itera por cada columna de píxeles desde 0 hasta WIDTH
* 2. Calcula la posición de la cámara en el espacio normalizado (-1 a 1)
* 3. Establece la dirección del rayo usando set_ray_direction()
* 4. Calcula el paso y distancia lateral en X usando set_ray_step_and_side_dist_formula()
* 5. Calcula el paso y distancia lateral en Y usando set_ray_step_and_side_dist_formula()
* 6. Ejecuta el algoritmo DDA para encontrar intersecciones con las paredes usando dda()
* 7. Calcula la distancia perpendicular a la pared usando wall_distance()
* 8. Determina la altura de la línea del rayo en pantalla usando ray_line_height()
* 9. Establece los puntos de inicio y fin del dibujo usando set_draw_start_and_end()
* 10. Dibuja la columna de la escena usando draw_scene_formula() (sin texturas)
* 11. Finalmente, muestra la imagen completa en pantalla usando GRAPHIC_put_image_to_window()
*
* @param data Puntero a la estructura principal que contiene todos los datos
* del juego incluyendo rayos, jugador, ventana gráfica y pantalla
*
* @note La función draw_scene_with_texture_formula() está comentada pero disponible
* para renderizado con texturas
*/

/**
* @brief Función principal del bucle de raycasting que renderiza la escena 3D
*
* Esta función realiza el algoritmo de raycasting para cada columna de píxeles
* de la pantalla, calculando qué se ve desde la posición del jugador.
*
* Pasos detallados:
* 1. Inicializa el contador x en -1 para recorrer todas las columnas de la pantalla
* 2. Para cada columna x (de 0 a WIDTH-1):
* a) Calcula camera_x: la posición de la cámara en el plano de proyección
* (va de -1 a 1, donde -1 es el lado izquierdo y 1 el derecho)
* b) Llama a set_ray_direction() para calcular la dirección del rayo
* c) Llama a set_ray_step_and_side_dist_formula() para el eje X:
* - Calcula si el rayo va hacia la izquierda o derecha (step_x)
* - Calcula la distancia hasta el siguiente lado vertical
* d) Llama a set_ray_step_and_side_dist_formula() para el eje Y:
* - Calcula si el rayo va hacia arriba o abajo (step_y)
* - Calcula la distancia hasta el siguiente lado horizontal
* e) Ejecuta dda() (Digital Differential Analyzer) para encontrar el muro
* f) Llama a wall_distance() para calcular la distancia perpendicular al muro
* g) Ejecuta ray_line_height() para calcular la altura de la línea a dibujar
* h) Llama a set_draw_start_and_end() para determinar dónde empezar y terminar de dibujar
* i) Dibuja la columna con draw_scene_formula() (sin texturas)
* - draw_scene_with_texture_formula() está comentada (con texturas)
* 3. Al final, muestra la imagen completa en pantalla con GRAPHIC_put_image_to_window()
*
* @param data Estructura principal que contiene toda la información del juego
* (jugador, rayos, pantalla, ventana, etc.)
*/
void raycasting_loop_formula(t_data *data)
{
int x;

x = -1;
while (++x < WIDTH)
{
data->ray.camera_x = 2 * x / (double)WIDTH - 1;
set_ray_direction(data);
data->ray.step_x = set_ray_step_and_side_dist_formula(data->ray.dir_x,
&data->ray.side_dist_x, data->ray.delta_dist_x,
data->player.pos_x, data->ray.map_x);
data->ray.step_y = set_ray_step_and_side_dist_formula(data->ray.dir_y,
&data->ray.side_dist_y, data->ray.delta_dist_y,
data->player.pos_y, data->ray.map_y);
dda(data);
wall_distance(data);
ray_line_height(data);
set_draw_start_and_end(data);
draw_scene_formula(data, x); // crea paredes sin texturas
//draw_scene_with_texture_formula(data, x); // crea paredes con texturas
}
GRAPHIC_put_image_to_window(data->root, data->win, data->screen, 0, 0);
}

/**
* @brief Función principal que ejecuta el motor de raycasting
*
* Esta función inicializa y ejecuta todo el sistema de raycasting paso a paso:
*
* 1. Crea una estructura de datos llamada 'data' y la limpia con memset()
* 2. Inicializa el sistema gráfico llamando a GRAPHIC_init()
* 3. Crea una ventana nueva con GRAPHIC_new_window() de tamaño WIDTH x HEIGHT
* 4. Crea una imagen en memoria con GRAPHIC_new_image() para dibujar
* 5. Obtiene los datos de la imagen con GRAPHIC_get_data_addr() para poder modificar píxeles
* 6. Carga todas las texturas necesarias usando texture_loading_formula()
* 7. Lee y procesa el mapa del juego con map_extraction_formula()
* 8. Encuentra la posición inicial del jugador con find_player()
* 9. Ejecuta el bucle principal de raycasting con raycasting_loop_formula()
* 10. Configura el evento para cerrar la ventana con GRAPHIC_hook() (tecla escape)
* 11. Configura los eventos de teclado con GRAPHIC_hook() para controlar el movimiento
* 12. Inicia el bucle principal del programa con GRAPHIC_loop()
* 13. Limpia toda la memoria al terminar con cleanup()
*
* @return 0 si la ejecución fue exitosa
*/
int RUN(void)
{
t_data data;

memset(&data, 0, sizeof(t_data));
[Link] = GRAPHIC_init();
[Link] = GRAPHIC_new_window([Link], WIDTH, HEIGHT, "Raycasting");
[Link] = GRAPHIC_new_image([Link], WIDTH, HEIGHT);
data.img_data = GRAPHIC_get_data_addr([Link], &[Link], &data.line_size,
&[Link]);
texture_loading_formula(&data);
map_extraction_formula(&data);
find_player(&data);
raycasting_loop_formula(&data);
GRAPHIC_hook([Link], 17, 0, close_game, &data);
GRAPHIC_hook([Link], 2, 1L << 0, key_press, &data);
GRAPHIC_loop([Link]);
cleanup(&data);
return (0);
}

También podría gustarte