Guest User

Untitled

a guest
Mar 18th, 2025
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.49 KB | None | 0 0
  1. #include <math.h>
  2. #include <float.h> // Для DBL_MAX
  3. #include <stdbool.h>
  4.  
  5. #include <stdio.h>
  6.  
  7.  
  8. #define WALL_SPACING 1
  9. #define MAX_VIEW_DISTANCE 10
  10.  
  11. #define MAIN_ROOM_HEIGHT 4
  12. #define MAIN_ROOM_WIDTH 4
  13.  
  14. #define PI 3.14159
  15.  
  16. #define RIGHT 0
  17. #define UP 1
  18. #define LEFT 2
  19. #define DOWN 3
  20.  
  21. // Данные о точке, расстоянии до неё относительно другой точки, ориентация в пространстве отсносительно неё
  22. struct point_and_distance {
  23.  
  24. double distance;
  25. double x;
  26. double y;
  27. int side;
  28.  
  29. };
  30.  
  31.  
  32.  
  33. char main_room_map[] = {1,1,1,1,
  34. 1,0,0,1,
  35. 1,0,0,1,
  36. 1,1,1,1 };
  37.  
  38. //=======================================================================================
  39. // Стандартные мат. функции
  40. double sqr(double value) {
  41.  
  42. return value*value;
  43.  
  44. }
  45.  
  46. double point_distance(double x_start, double y_start, double x_end, double y_end) {
  47.  
  48. return sqrt( sqr(x_end - x_start) + sqr(y_end - y_start) );
  49.  
  50. }
  51.  
  52. //=========================================================================================
  53. // Нахождение координаты (x) для горизонтальной прямой, с известной координатой (y)
  54. double horizontal_border_intersection_x(double x_start, double y_start, double wall_y, double angle) {
  55.  
  56. return ( (wall_y - y_start) / tan(angle) ) + x_start;
  57.  
  58. }
  59. // Нахождение координаты (y) для вертикальной прямой, с известной координатой (x)
  60. double vertical_border_intersection_y(double x_start, double y_start, double wall_x, double angle) {
  61.  
  62. return tan(angle) * (wall_x - x_start) + y_start;
  63.  
  64. }
  65. //=========================================================================================
  66. // Нахождение расстояния и точки пересечения для 4-ёх границ тайла в виде структуры
  67. void calculate_down_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Нижняя граница
  68.  
  69. border_data -> y = floor(y_start / WALL_SPACING) * WALL_SPACING;
  70. border_data -> x = horizontal_border_intersection_x(x_start, y_start, border_data -> y, angle);
  71.  
  72. border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
  73.  
  74. border_data -> side = DOWN;
  75.  
  76. }
  77. void calculate_up_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Вверхняя граница
  78.  
  79. border_data -> y = ceil(y_start / WALL_SPACING) * WALL_SPACING;
  80. border_data -> x = horizontal_border_intersection_x(x_start, y_start, border_data -> y, angle);
  81.  
  82. border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
  83.  
  84. border_data -> side = UP;
  85.  
  86. }
  87. void calculate_left_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Левая граница
  88.  
  89. border_data -> x = floor(x_start / WALL_SPACING) * WALL_SPACING;
  90. border_data -> y = vertical_border_intersection_y(x_start, y_start, border_data -> x, angle);
  91.  
  92. border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
  93.  
  94. border_data -> side = LEFT;
  95.  
  96. }
  97. void calculate_right_border_data(double x_start, double y_start, double angle, struct point_and_distance* border_data) { // Правая граница
  98.  
  99. border_data -> x = ceil(x_start/WALL_SPACING)*WALL_SPACING;
  100. border_data -> y = vertical_border_intersection_y(x_start, y_start, border_data -> x, angle);
  101.  
  102. border_data -> distance = point_distance(x_start, y_start, border_data -> x, border_data -> y);
  103.  
  104. border_data -> side = RIGHT;
  105.  
  106. }
  107. //=========================================================================================
  108. // Проверка на существование препятствия в соотвествии с направлением луча
  109. bool wall_check(int x_start_tile, int y_start_tile, int wall_side, char* map, int width, int height) {
  110.  
  111. // Если какая то из начальных координат выходит за границы карты
  112. if (x_start_tile < 0 || x_start_tile >= width || y_start_tile < 0 || y_start_tile >= height) {
  113. return true;
  114. }
  115.  
  116. int index = 0;
  117.  
  118. switch(wall_side) {
  119.  
  120. case RIGHT: if (x_start_tile + 1 < width) {
  121.  
  122. index = x_start_tile + 1 + (width*y_start_tile);
  123. return *(map + index);
  124.  
  125. }
  126. break;
  127.  
  128. case UP: if (y_start_tile + 1 < height) {
  129.  
  130. index = x_start_tile + ( width*(y_start_tile + 1) );
  131. return *(map + index);
  132.  
  133. }
  134. break;
  135.  
  136. case LEFT: if (x_start_tile - 1 >= 0) {
  137.  
  138. index = x_start_tile - 1 + (width*y_start_tile);
  139. return *(map + index);
  140. }
  141. break;
  142.  
  143. case DOWN: if (y_start_tile - 1 >= 0) {
  144.  
  145. index = x_start_tile + (width*(y_start_tile - 1) );
  146. return *(map + index);
  147.  
  148. }
  149. break;
  150.  
  151. default: return false;
  152. break;
  153.  
  154. }
  155.  
  156. return true; // Выполнится, если произошло столкновение с границой карты
  157.  
  158. }
  159.  
  160. //=========================================================================================
  161. // Тяжёлая артиллерия
  162. double ray_length_to_wall(double* x_start_ptr, double* y_start_ptr, double angle) {
  163.  
  164. double x_start = *x_start_ptr;
  165. double y_start = *y_start_ptr;
  166.  
  167. int x_start_tile = (int)floor(x_start/WALL_SPACING);
  168. int y_start_tile = (int)floor(y_start/WALL_SPACING);
  169.  
  170.  
  171. if (angle >= (3*PI)/2) { // Для угла >270
  172.  
  173. //=======================================================================================================
  174. struct point_and_distance down_border_data;
  175. calculate_down_border_data(x_start, y_start, angle, &down_border_data);
  176.  
  177. struct point_and_distance right_border_data;
  178. calculate_right_border_data(x_start, y_start, angle, &right_border_data);
  179.  
  180. struct point_and_distance* first_intersection;
  181. first_intersection = (down_border_data.distance) < (right_border_data.distance) ? &down_border_data : &right_border_data;
  182.  
  183.  
  184. if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
  185. return first_intersection -> distance;
  186. }
  187. else {
  188. *x_start_ptr = first_intersection -> x;
  189. *y_start_ptr = first_intersection -> y;
  190. return -1;
  191. }
  192.  
  193. }
  194.  
  195. else if (angle >= PI) { // Для угла >180
  196.  
  197. //=======================================================================================================
  198. struct point_and_distance left_border_data;
  199. calculate_left_border_data(x_start, y_start, angle, &left_border_data);
  200.  
  201. struct point_and_distance down_border_data;
  202. calculate_down_border_data(x_start, y_start, angle, &down_border_data);
  203.  
  204. struct point_and_distance* first_intersection;
  205. first_intersection = (left_border_data.distance) < (down_border_data.distance) ? &left_border_data : &down_border_data;
  206.  
  207.  
  208. if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
  209. return first_intersection -> distance;
  210. }
  211. else {
  212. *x_start_ptr = first_intersection -> x;
  213. *y_start_ptr = first_intersection -> y;
  214. return -1;
  215. }
  216.  
  217. }
  218.  
  219. else if (angle >= PI/2) { // Для угла >90
  220.  
  221. //=======================================================================================================
  222. struct point_and_distance up_border_data;
  223. calculate_up_border_data(x_start, y_start, angle, &up_border_data);
  224.  
  225. struct point_and_distance right_border_data;
  226. calculate_right_border_data(x_start, y_start, angle, &right_border_data);
  227.  
  228. struct point_and_distance* first_intersection;
  229. first_intersection = (up_border_data.distance) < (right_border_data.distance) ? &up_border_data : &right_border_data;
  230.  
  231.  
  232. if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
  233. return first_intersection -> distance;
  234. }
  235. else {
  236. *x_start_ptr = first_intersection -> x;
  237. *y_start_ptr = first_intersection -> y;
  238. return -1;
  239. }
  240.  
  241.  
  242. }
  243.  
  244. else if (angle < PI/2) { // Для угла <90
  245.  
  246. //=======================================================================================================
  247. struct point_and_distance right_border_data;
  248. calculate_right_border_data(x_start, y_start, angle, &right_border_data);
  249.  
  250. struct point_and_distance up_border_data;
  251. calculate_up_border_data(x_start, y_start, angle, &up_border_data);
  252.  
  253. struct point_and_distance* first_intersection;
  254. first_intersection = (right_border_data.distance) < (up_border_data.distance) ? &right_border_data : &up_border_data;
  255.  
  256.  
  257. if ( wall_check(x_start_tile, y_start_tile, first_intersection -> side, main_room_map, MAIN_ROOM_WIDTH, MAIN_ROOM_HEIGHT) ) {
  258. return first_intersection -> distance;
  259. }
  260. else {
  261. *x_start_ptr = first_intersection -> x;
  262. *y_start_ptr = first_intersection -> y;
  263. return -1;
  264. }
  265.  
  266.  
  267.  
  268. }
  269.  
  270. } // Конец функции
  271.  
  272.  
  273.  
  274. void main(void) {
  275.  
  276. double player_x = 1.2123;
  277. double player_y = 1.3421;
  278. double angle = 0;
  279.  
  280. double x_start = player_x;
  281. double y_start = player_y;
  282.  
  283. double distance = DBL_MAX;
  284.  
  285. for(int i = 0; i < MAX_VIEW_DISTANCE; i++) {
  286.  
  287. if (distance = ray_length_to_wall(&x_start, &y_start, angle) != -1) {
  288. break;
  289. }
  290.  
  291. }
  292.  
  293. printf("distance is %f", distance);
  294.  
  295.  
  296. }
Add Comment
Please, Sign In to add comment