Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <math.h>
- #include <float.h> // Для DBL_MAX
- #include <stdbool.h>
- #include <stdio.h>
- #define WALL_SPACING 1
- #define MAX_VIEW_DISTANCE 10
- #define MAIN_ROOM_HEIGHT 4
- #define MAIN_ROOM_WIDTH 4
- #define PI 3.14159
- #define RIGHT 0
- #define UP 1
- #define LEFT 2
- #define DOWN 3
- // Данные о точке, расстоянии до неё относительно другой точки, ориентация в пространстве отсносительно неё
- struct point_and_distance {
- double distance;
- double x;
- double y;
- int side;
- };
- char main_room_map[] = {1,1,1,1,
- 1,0,0,1,
- 1,0,0,1,
- 1,1,1,1 };
- //=======================================================================================
- // Стандартные мат. функции
- double sqr(double value) {
- return value*value;
- }
- double point_distance(double x_start, double y_start, double x_end, double y_end) {
- return sqrt( sqr(x_end - x_start) + sqr(y_end - y_start) );
- }
- //=========================================================================================
- // Нахождение координаты (x) для горизонтальной прямой, с известной координатой (y)
- double horizontal_border_intersection_x(double x_start, double y_start, double wall_y, double angle) {
- return ( (wall_y - y_start) / tan(angle) ) + x_start;
- }
- // Нахождение координаты (y) для вертикальной прямой, с известной координатой (x)
- double vertical_border_intersection_y(double x_start, double y_start, double wall_x, double angle) {
- return tan(angle) * (wall_x - x_start) + y_start;
- }
- //=========================================================================================
- // Нахождение расстояния и точки пересечения для 4-ёх границ тайла в виде структуры
- void calculate_down_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Нижняя граница
- border_data -> y = floor(y_start / WALL_SPACING) * WALL_SPACING;
- border_data -> x = horizontal_border_intersection_x(x_start, y_start, border_data -> y, angle);
- border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
- border_data -> side = DOWN;
- }
- void calculate_up_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Вверхняя граница
- border_data -> y = ceil(y_start / WALL_SPACING) * WALL_SPACING;
- border_data -> x = horizontal_border_intersection_x(x_start, y_start, border_data -> y, angle);
- border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
- border_data -> side = UP;
- }
- void calculate_left_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Левая граница
- border_data -> x = floor(x_start / WALL_SPACING) * WALL_SPACING;
- border_data -> y = vertical_border_intersection_y(x_start, y_start, border_data -> x, angle);
- border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
- border_data -> side = LEFT;
- }
- void calculate_right_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Правая граница
- border_data -> x = ceil(x_start/WALL_SPACING)*WALL_SPACING;
- border_data -> y = vertical_border_intersection_y(x_start, y_start, border_data -> x, angle);
- border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
- border_data -> side = RIGHT;
- }
- //=========================================================================================
- // Проверка на существование препятствия в соотвествии с направлением луча
- bool wall_check(int x_start_tile, int y_start_tile, int wall_side, char* map, int width, int height) {
- // Если какая то из начальных координат выходит за границы карты
- if (x_start_tile < 0 || x_start_tile >= width || y_start_tile < 0 || y_start_tile >= height) {
- return true;
- }
- int index = 0;
- switch(wall_side) {
- case RIGHT: if (x_start_tile + 1 < width) {
- index = x_start_tile + 1 + (width*y_start_tile);
- return *(map + index);
- }
- break;
- case UP: if (y_start_tile + 1 < height) {
- index = x_start_tile + ( width*(y_start_tile + 1) );
- return *(map + index);
- }
- break;
- case LEFT: if (x_start_tile - 1 >= 0) {
- index = x_start_tile - 1 + (width*y_start_tile);
- return *(map + index);
- }
- break;
- case DOWN: if (y_start_tile - 1 >= 0) {
- index = x_start_tile + (width*(y_start_tile - 1) );
- return *(map + index);
- }
- break;
- default: return false;
- break;
- }
- return true; // Выполнится, если произошло столкновение с границой карты
- }
- //=========================================================================================
- // Тяжёлая артиллерия
- double ray_length_to_wall(double* x_start_ptr, double* y_start_ptr, double angle) {
- double x_start = *x_start_ptr;
- double y_start = *y_start_ptr;
- int x_start_tile = (int)floor(x_start/WALL_SPACING);
- int y_start_tile = (int)floor(y_start/WALL_SPACING);
- if (angle >= (3*PI)/2) { // Для угла >270
- //=======================================================================================================
- struct point_and_distance down_border_data;
- calculate_down_border_data(x_start, y_start, angle, &down_border_data);
- struct point_and_distance right_border_data;
- calculate_right_border_data(x_start, y_start, angle, &right_border_data);
- struct point_and_distance* first_intersection;
- first_intersection = (down_border_data.distance) < (right_border_data.distance) ? &down_border_data : &right_border_data;
- if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
- return first_intersection -> distance;
- }
- else {
- *x_start_ptr = first_intersection -> x;
- *y_start_ptr = first_intersection -> y;
- return -1;
- }
- }
- else if (angle >= PI) { // Для угла >180
- //=======================================================================================================
- struct point_and_distance left_border_data;
- calculate_left_border_data(x_start, y_start, angle, &left_border_data);
- struct point_and_distance down_border_data;
- calculate_down_border_data(x_start, y_start, angle, &down_border_data);
- struct point_and_distance* first_intersection;
- first_intersection = (left_border_data.distance) < (down_border_data.distance) ? &left_border_data : &down_border_data;
- if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
- return first_intersection -> distance;
- }
- else {
- *x_start_ptr = first_intersection -> x;
- *y_start_ptr = first_intersection -> y;
- return -1;
- }
- }
- else if (angle >= PI/2) { // Для угла >90
- //=======================================================================================================
- struct point_and_distance up_border_data;
- calculate_up_border_data(x_start, y_start, angle, &up_border_data);
- struct point_and_distance right_border_data;
- calculate_right_border_data(x_start, y_start, angle, &right_border_data);
- struct point_and_distance* first_intersection;
- first_intersection = (up_border_data.distance) < (right_border_data.distance) ? &up_border_data : &right_border_data;
- if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
- return first_intersection -> distance;
- }
- else {
- *x_start_ptr = first_intersection -> x;
- *y_start_ptr = first_intersection -> y;
- return -1;
- }
- }
- else if (angle < PI/2) { // Для угла <90
- //=======================================================================================================
- struct point_and_distance right_border_data;
- calculate_right_border_data(x_start, y_start, angle, &right_border_data);
- struct point_and_distance up_border_data;
- calculate_up_border_data(x_start, y_start, angle, &up_border_data);
- struct point_and_distance* first_intersection;
- first_intersection = (right_border_data.distance) < (up_border_data.distance) ? &right_border_data : &up_border_data;
- if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
- return first_intersection -> distance;
- }
- else {
- *x_start_ptr = first_intersection -> x;
- *y_start_ptr = first_intersection -> y;
- return -1;
- }
- }
- } // Конец функции
- void main(void) {
- double player_x = 1.2123;
- double player_y = 1.3421;
- double angle = 0;
- double x_start = player_x;
- double y_start = player_y;
- double distance = DBL_MAX;
- for(int i = 0; i < MAX_VIEW_DISTANCE; i++) {
- if (distance = ray_length_to_wall(&x_start, &y_start, angle) != -1) {
- break;
- }
- }
- printf("distance is %f", distance);
- }
Add Comment
Please, Sign In to add comment