Advertisement
Guest User

Untitled

a guest
Mar 26th, 2025
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.45 KB | None | 0 0
  1. #include <math.h>
  2. #include <float.h> // Для DBL_MAX
  3. #include <stdbool.h>
  4. #include <stdlib.h>
  5.  
  6. #include <stdio.h>
  7.  
  8. #define PI 3.14159
  9.  
  10. #define RIGHT 0
  11. #define UP 1
  12. #define LEFT 2
  13. #define DOWN 3
  14.  
  15.  
  16. // Шаблон для комнат
  17. struct room_struct {
  18.  
  19. bool* map;
  20.  
  21. int width;
  22. int height;
  23.  
  24. };
  25.  
  26. struct unit_struct {
  27.  
  28. double x;
  29. double y;
  30.  
  31. double angle;
  32. double rotate_speed;
  33.  
  34. };
  35.  
  36.  
  37. //=========================================================================================
  38. // Стандартные мат. функции
  39. double sqr(double value) {
  40.  
  41. return value*value;
  42.  
  43. }
  44.  
  45. double point_distance(double x_start, double y_start, double x_end, double y_end) {
  46.  
  47. return sqrt( sqr(x_end - x_start) + sqr(y_end - y_start) );
  48.  
  49. }
  50.  
  51. double min(double value_1, double value_2) {
  52.  
  53. return (value_1 < value_2) ? value_1 : value_2;
  54. }
  55.  
  56. double max(double value_1, double value_2) {
  57.  
  58. return (value_1 > value_2) ? value_1 : value_2;
  59. }
  60.  
  61. //=========================================================================================
  62.  
  63. // Проверка на существование горизонтальной или вертикальной стены
  64. bool wall_check(int tile_number_x, int tile_number_y, int wall_side, struct room_struct room) {
  65.  
  66.  
  67.  
  68. // Если какая то из начальных координат выходит за границы карты
  69. if (tile_number_x < 0 || tile_number_x >= room.width || tile_number_y < 0 || tile_number_y >= room.height) {
  70. return true;
  71. }
  72.  
  73. int index = 0;
  74.  
  75. switch(wall_side) {
  76.  
  77. case RIGHT: if (++tile_number_x < room.width) {
  78.  
  79. index = tile_number_x + (room.width * tile_number_y);
  80. return room.map[index];
  81.  
  82. }
  83. break;
  84.  
  85. case UP: if (--tile_number_y >= 0) {
  86.  
  87. index = tile_number_x + (room.width * tile_number_y);
  88. return room.map[index];
  89.  
  90. }
  91. break;
  92.  
  93. case LEFT: if (--tile_number_x >= 0) {
  94.  
  95. index = tile_number_x + (room.width * tile_number_y);
  96. return room.map[index];
  97.  
  98. }
  99. break;
  100.  
  101. case DOWN: if (++tile_number_y < room.height) {
  102.  
  103. index = tile_number_x + (room.width * tile_number_y);
  104. return room.map[index];
  105.  
  106. }
  107. break;
  108.  
  109. default:
  110.  
  111. abort();
  112.  
  113. break;
  114.  
  115. }
  116.  
  117. return true; // Стена при достижении границы карты по дефолту
  118.  
  119.  
  120. }
  121.  
  122. // Поиск расстояния до ближайшей горизонтальной стены (вверхние и нижние)
  123. double find_horizontal_wall_distance(double x_start, double y_start, double angle, struct room_struct room, double max_view_distance, int wall_spacing, int side) {
  124.  
  125. int left_border_num = (int)floor( x_start / wall_spacing);
  126. int up_border_num = (int)floor( y_start / wall_spacing);
  127.  
  128. int offset;
  129. int current_border_num;
  130.  
  131. bool wall_exist;
  132.  
  133. double distance;
  134.  
  135. const int max_border_check = (int)ceil(max_view_distance);
  136.  
  137.  
  138. if (side == UP) {
  139. offset = -1;
  140. current_border_num = up_border_num;
  141. }
  142.  
  143. else if (side == DOWN) {
  144. offset = 1;
  145. current_border_num = up_border_num + 1;
  146. }
  147.  
  148. else {
  149. abort();
  150. }
  151.  
  152. for(int i = 0; i < max_border_check; i++) {
  153.  
  154. double y_intersection = ( current_border_num + i*offset ) * wall_spacing; // Константно для номера(индекса) стены
  155. double x_intersection = ( (y_intersection - y_start) / (-tan(angle)) ) + x_start; // Зависит от угла обзора
  156.  
  157.  
  158. // ВАЖНО :
  159. // передаются координаты того тайла, на котором стоял бы юнит, если бы
  160. // смотрел на стену по направлению side
  161.  
  162. int y_intersection_tile = up_border_num + i*offset;
  163. int x_intersection_tile = (int)floor(x_intersection / wall_spacing);
  164.  
  165. wall_exist = wall_check(x_intersection_tile, y_intersection_tile, side, room);
  166.  
  167. // Если обнаружена стена или эта итерация последняя
  168. if (wall_exist || i + 1 >= max_border_check) {
  169.  
  170. distance = point_distance(x_start, y_start, x_intersection, y_intersection);
  171.  
  172. if ( distance > max_view_distance) {
  173. distance = max_view_distance;
  174. }
  175.  
  176. break;
  177.  
  178. }
  179.  
  180. }
  181.  
  182. return distance;
  183.  
  184. }
  185.  
  186. // Поиск расстояния до ближайшей вертикальной стены (правые и левые)
  187. double find_vertical_wall_distance(double x_start, double y_start, double angle, struct room_struct room, double max_view_distance, int wall_spacing, int side) {
  188.  
  189. int left_border_num = (int)floor( x_start / wall_spacing);
  190. int up_border_num = (int)floor( y_start / wall_spacing);
  191.  
  192. int offset;
  193. int current_border_num;
  194.  
  195. bool wall_exist;
  196. double distance = max_view_distance;
  197.  
  198. const int max_border_check = (int)ceil(max_view_distance);
  199.  
  200. if (side == LEFT) {
  201. offset = -1;
  202. current_border_num = left_border_num;
  203. }
  204.  
  205. else if (side == RIGHT) {
  206. offset = 1;
  207. current_border_num = left_border_num + 1;
  208. }
  209.  
  210. else {
  211. abort();
  212. }
  213.  
  214.  
  215. for(int i = 0; i < max_border_check; i++) {
  216.  
  217. double x_intersection = ( current_border_num + i*offset ) * wall_spacing; // Константа от номера(индекса) стены
  218. double y_intersection = ( -tan(angle) * (x_intersection - x_start) ) + y_start; // Зависит от угла обзора
  219.  
  220.  
  221. // ВАЖНО :
  222. // передаются координаты того тайла, на котором стоял бы юнит, если бы
  223. // смотрел на стену по направлению side
  224.  
  225. int x_intersection_tile = left_border_num + i*offset;
  226. int y_intersection_tile = (int)floor(y_intersection / wall_spacing);
  227.  
  228. wall_exist = wall_check(x_intersection_tile, y_intersection_tile, side, room);
  229.  
  230. // Если обнаружена стена или эта итерация последняя
  231. if (wall_exist || i + 1 >= max_border_check) {
  232.  
  233. distance = point_distance(x_start, y_start, x_intersection, y_intersection);
  234.  
  235. if ( distance > max_view_distance) {
  236. distance = max_view_distance;
  237. }
  238.  
  239. break;
  240.  
  241. }
  242.  
  243.  
  244. }
  245.  
  246.  
  247. return distance;
  248.  
  249. }
  250.  
  251. //=========================================================================================
  252. // Тяжёлая артиллерия
  253. double ray_length_to_wall(double x_start, double y_start, double angle, struct room_struct room, double max_view_distance, int wall_spacing) {
  254.  
  255. if (angle >= (3*PI)/2) { // 1) Для угла >270
  256. //=======================================================================================================
  257.  
  258. double down_wall_distance = find_horizontal_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, DOWN);
  259. double right_wall_distance = find_vertical_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, RIGHT);
  260.  
  261. return min(down_wall_distance, right_wall_distance);
  262.  
  263. }
  264.  
  265. else if (angle >= PI) { // 2) Для угла >180
  266. //=======================================================================================================
  267.  
  268. double left_wall_distance = find_vertical_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, LEFT);
  269. double down_wall_distance = find_horizontal_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, DOWN);
  270.  
  271. return min(left_wall_distance, down_wall_distance);
  272. }
  273.  
  274. else if (angle >= PI/2) { // 3) Для угла >90
  275. //=======================================================================================================
  276.  
  277. double up_wall_distance = find_horizontal_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, UP);
  278. double left_wall_distance = find_vertical_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, LEFT);
  279.  
  280. return min(up_wall_distance, left_wall_distance);
  281.  
  282. }
  283.  
  284. else if (angle < PI/2) { // 4) Для угла <90
  285. //=======================================================================================================
  286.  
  287. double right_wall_distance = find_vertical_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, RIGHT);
  288. double up_wall_distance = find_horizontal_wall_distance(x_start, y_start, angle, room, max_view_distance, wall_spacing, UP);
  289.  
  290. return min(right_wall_distance, up_wall_distance);
  291.  
  292. }
  293.  
  294. return -1;
  295.  
  296. } // Конец функции
  297.  
  298.  
  299. int main(void) {
  300.  
  301. //=======================================================================================================
  302. // Создание начальной комнаты
  303.  
  304. struct room_struct main_room;
  305.  
  306. main_room.width = 3;
  307. main_room.height = 3;
  308.  
  309. main_room.map = malloc( sizeof(*main_room.map) * main_room.width * main_room.height );
  310.  
  311. if (main_room.map == NULL) {
  312. abort();
  313. }
  314. else {
  315. /////////////////////////////////////////////////////////////////
  316. main_room.map[0] = 0; main_room.map[1] = 0; main_room.map[2] = 0;
  317. main_room.map[3] = 0; main_room.map[4] = 0; main_room.map[5] = 0;
  318. main_room.map[6] = 0; main_room.map[7] = 0; main_room.map[8] = 0;
  319. /////////////////////////////////////////////////////////////////
  320.  
  321. }
  322.  
  323. struct room_struct* current_room = &main_room; // Мейн рум устанавливается как стартовая
  324.  
  325. //=======================================================================================================
  326. // Преднастройка параметров рендеринга
  327.  
  328. double max_view_distance = max(current_room -> width, current_room -> height);
  329. int wall_spacing = 1;
  330.  
  331.  
  332. //=======================================================================================================
  333. // Создание персонажа
  334.  
  335. struct unit_struct player;
  336.  
  337. player.x = 1.01;
  338. player.y = 1.01;
  339.  
  340. player.angle = 0.01;
  341. player.rotate_speed = PI/30;
  342.  
  343.  
  344.  
  345. //=======================================================================================================
  346.  
  347. printf("%f\n", ray_length_to_wall( player.x, player.y, player.angle, *current_room, max_view_distance, wall_spacing) );
  348. printf("%f\n", ray_length_to_wall( player.x, player.y, player.angle + PI/2, *current_room, max_view_distance, wall_spacing) );
  349. printf("%f\n", ray_length_to_wall( player.x, player.y, player.angle + PI, *current_room, max_view_distance, wall_spacing) );
  350. printf("%f\n", ray_length_to_wall( player.x, player.y, player.angle + (3*PI)/2, *current_room, max_view_distance, wall_spacing) );
  351.  
  352.  
  353. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement