Das Programmierspiel von der Gulasch-Programmier-Nacht 11

(Latest mirror + merged latest fork by qr4 on Lua 5.3)

Entropia info page https://entropia.de/GPN11:Programmierspiel (dead links)
Origin Gitlab
https://code.nerd2nerd.org/n2n/WeltraumProgrammierNacht

screen.c 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <sys/time.h>
  4. #include <SDL/SDL.h>
  5. #include <SDL/SDL_gfxPrimitives.h>
  6. #include <errno.h>
  7. #include "globals.h"
  8. #include "screen.h"
  9. #include "route.h"
  10. #include "json_output.h"
  11. /* TODO:
  12. *
  13. * a global scene for easy rerender
  14. * fast image switch
  15. */
  16. SDL_Surface *screen;
  17. void sdl_setup() {
  18. const SDL_VideoInfo *info;
  19. if (SDL_Init(SDL_INIT_VIDEO) == -1) {
  20. fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
  21. exit(1);
  22. }
  23. info = SDL_GetVideoInfo();
  24. GLOBALS.DISPLAY_WIDTH = info->current_w;
  25. GLOBALS.DISPLAY_HEIGHT = info->current_h;
  26. atexit(SDL_Quit);
  27. }
  28. void sdl_screen_init() {
  29. if (GLOBALS.FULLSCREEN) {
  30. screen = SDL_SetVideoMode(GLOBALS.DISPLAY_WIDTH, GLOBALS.DISPLAY_HEIGHT, 0, SDL_FULLSCREEN);
  31. } else {
  32. screen = SDL_SetVideoMode(GLOBALS.WIDTH, GLOBALS.HEIGHT, 0, 0);
  33. }
  34. }
  35. void sdl_init() {
  36. sdl_setup();
  37. sdl_screen_init();
  38. if (screen == NULL) {
  39. fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
  40. exit(1);
  41. }
  42. }
  43. void draw_line(vector_t* p1, vector_t* p2) {
  44. aalineRGBA(screen, p1->x, p1->y, p2->x, p2->y, 255, 255, 255, 255);
  45. }
  46. void draw_blob(cluster_t* p) {
  47. if(p->safety_radius > 0) {
  48. aacircleRGBA(screen, p->center.x, p->center.y, 2, 255, 255, 255, 255);
  49. aacircleRGBA(screen, p->center.x, p->center.y, p->safety_radius, 64, 64, 64, 255);
  50. }
  51. }
  52. void draw_clusters(cluster_t* clusters, int n) {
  53. int x, y;
  54. for (y = 0; y < n; y++) {
  55. for (x = 0; x < n; x++) {
  56. draw_blob(&clusters[y*n + x]);
  57. }
  58. }
  59. }
  60. void draw_grid(cluster_t *clusters, int n) {
  61. int x, y;
  62. for (y = 0; y < n - 1; y++) {
  63. for (x = 0; x < n - 1; x++) {
  64. draw_line(&(clusters[y*n + x].center), &(clusters[y*n + x + 1].center));
  65. draw_line(&(clusters[y*n + x].center), &(clusters[(y + 1)*n + x].center));
  66. }
  67. draw_line(&(clusters[y*n + x].center), &(clusters[(y + 1)*n + x].center));
  68. }
  69. for (x = 0; x < n - 1; x++) {
  70. draw_line(&(clusters[y*n + x].center), &(clusters[y*n + x + 1].center));
  71. }
  72. }
  73. void draw_route(waypoint_t* route, int r, int g, int b, int with_blobs) {
  74. if (route == NULL) return;
  75. waypoint_t* t = route;
  76. while (t->next != NULL) {
  77. if (with_blobs) aacircleRGBA(screen, t->point.x, t->point.y, 2, r, g, b, 255);
  78. aalineRGBA(screen, t->point.x, t->point.y, t->next->point.x, t->next->point.y, r, g, b, 128);
  79. t = t->next;
  80. }
  81. aacircleRGBA(screen, t->point.x, t->point.y, 2, r, g, g, 255);
  82. }
  83. void squirl(cluster_t *clusters, int n) {
  84. int i, j;
  85. for (i = 1; i < n-1; i++) {
  86. for (j = 1; j < n-1; j++) {
  87. float x = clusters[i*n + j].center.x;
  88. float y = clusters[i*n + j].center.y;
  89. float r = hypotf(x-GLOBALS.WIDTH / 2, y - GLOBALS.HEIGHT/2);
  90. float phi = atan2f(y-GLOBALS.HEIGHT / 2, x - GLOBALS.WIDTH/2);
  91. float angle = (8e-4 * r - 0.35);
  92. phi += angle;
  93. x = GLOBALS.WIDTH/2 + r*cos(phi);
  94. y = GLOBALS.HEIGHT/2 + r * sin(phi);
  95. clusters[i*n + j].center.x = x;
  96. clusters[i*n + j].center.y = y;
  97. }
  98. }
  99. }
  100. void randomize(cluster_t *clusters, int n, float fac) {
  101. int i, j;
  102. for (i = 1; i < n-1; i++) {
  103. for (j = 1; j < n-1; j++) {
  104. clusters[i*n + j].center.x += (((float) rand() / RAND_MAX) - 0.5) * 2 * fac;
  105. clusters[i*n + j].center.y += (((float) rand() / RAND_MAX) - 0.5) * 2 * fac;
  106. }
  107. }
  108. }
  109. void set(cluster_t *clusters, int n, float safety_radius) {
  110. int x, y;
  111. for (y = 0; y < n; y++) {
  112. for (x = 0; x < n; x++) {
  113. clusters[y*n + x].center.x = GLOBALS.WIDTH * x / (n - 1);
  114. clusters[y*n + x].center.y = GLOBALS.HEIGHT * y / (n - 1);
  115. if(x == 0 || y == 0 || x == n-1 || y == n-1) {
  116. // Not a real point, just used to extend the grid to the window size
  117. clusters[y*n + x].safety_radius = 0;
  118. } else {
  119. clusters[y*n + x].safety_radius = (y*n+x)%5 ? safety_radius : safety_radius/2;
  120. }
  121. }
  122. }
  123. squirl(clusters, n);
  124. }
  125. int main_loop() {
  126. int quit = 0;
  127. int n = 16;
  128. int view_grid = 0;
  129. int view_points = 1;
  130. int view_waypoints = 1;
  131. int view_smoothed = 1;
  132. int view_json = 0;
  133. int safety_radius = GLOBALS.HEIGHT / (n + 1) / 5;
  134. float fac = GLOBALS.WIDTH / (n + 1) * 0.3;
  135. SDL_Event e;
  136. vector_t start = {{0, 0}};
  137. vector_t stop = {{0, 0}};
  138. waypoint_t* route1 = NULL;
  139. waypoint_t* route1s = NULL;
  140. waypoint_t* route2 = NULL;
  141. waypoint_t* route2s = NULL;
  142. waypoint_t* route3 = NULL;
  143. waypoint_t* route3s = NULL;
  144. char needJsonOutput = 0;
  145. struct timeval t1, t2;
  146. double elapsedTime;
  147. cluster_t* clusters = malloc (sizeof(cluster_t) * n * n);
  148. set(clusters, n, safety_radius);
  149. while (!quit) {
  150. safety_radius = GLOBALS.HEIGHT / (n + 1) / 5 ;
  151. SDL_FillRect( SDL_GetVideoSurface(), NULL, 0 );
  152. if (view_grid) {
  153. draw_grid(clusters, n);
  154. }
  155. if (view_points) {
  156. draw_clusters(clusters, n);
  157. }
  158. if (view_waypoints) {
  159. draw_route(route1, 0, 0, 255, 1);
  160. draw_route(route2, 0, 255, 0, 1);
  161. draw_route(route3, 255, 0, 0, 1);
  162. }
  163. if (view_smoothed) {
  164. draw_route(route1s, 0, 255, 255, 0);
  165. draw_route(route2s, 128, 255, 128, 0);
  166. draw_route(route3s, 255, 255, 0, 0);
  167. }
  168. if (start.x != 0 && start.y != 0) {
  169. aacircleRGBA(screen, start.x, start.y, 2, 0, 255, 0, 255);
  170. }
  171. if (stop.x != 0 && stop.y != 0) {
  172. aacircleRGBA(screen, stop.x, stop.y, 2, 255, 0, 0, 255);
  173. }
  174. SDL_Flip(screen);
  175. SDL_WaitEvent(&e);
  176. needJsonOutput = view_json;
  177. switch (e.type) {
  178. case SDL_QUIT :
  179. quit = 1;
  180. break;
  181. case SDL_MOUSEBUTTONDOWN :
  182. switch (e.button.button) {
  183. case SDL_BUTTON_LEFT:
  184. start.x = e.button.x;
  185. start.y = e.button.y;
  186. break;
  187. case SDL_BUTTON_RIGHT:
  188. stop.x = e.button.x;
  189. stop.y = e.button.y;
  190. break;
  191. }
  192. if (start.x != 0 && start.y != 0) {
  193. aacircleRGBA(screen, start.x, start.y, 2, 0, 255, 0, 255);
  194. }
  195. if (stop.x != 0 && stop.y != 0) {
  196. aacircleRGBA(screen, stop.x, stop.y, 2, 255, 0, 0, 255);
  197. }
  198. SDL_Flip(screen);
  199. if (start.x != 0 && start.y != 0 && stop.x != 0 && stop.y != 0) {
  200. fprintf(stderr, "\n\nRoute from (%f,%f) to (%f,%f)\n", start.x, start.y, stop.x, stop.y);
  201. gettimeofday(&t1, NULL);
  202. route1 = plotCourse(&start, &stop, clusters, n);
  203. gettimeofday(&t2, NULL);
  204. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  205. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  206. fprintf(stderr, "plotCourse scanline based took %f ms\n", elapsedTime);
  207. gettimeofday(&t1, NULL);
  208. route1s = smooth(route1, 5);
  209. gettimeofday(&t2, NULL);
  210. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  211. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  212. fprintf(stderr, "smoth scanline based route took %f ms\n", elapsedTime);
  213. gettimeofday(&t1, NULL);
  214. route2 = plotCourse_scanline_gridbased(&start, &stop, clusters, n);
  215. gettimeofday(&t2, NULL);
  216. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  217. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  218. fprintf(stderr, "plotCourse scanline based gridbased took %f ms\n", elapsedTime);
  219. gettimeofday(&t1, NULL);
  220. route2s = smooth(route2, 5);
  221. gettimeofday(&t2, NULL);
  222. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  223. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  224. fprintf(stderr, "smoth scanline based gridbased route took %f ms\n", elapsedTime);
  225. gettimeofday(&t1, NULL);
  226. route3 = plotCourse_gridbased(&start, &stop, clusters, n);
  227. gettimeofday(&t2, NULL);
  228. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  229. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  230. fprintf(stderr, "plotCourse gridline based took %f ms\n", elapsedTime);
  231. gettimeofday(&t1, NULL);
  232. route3s = smooth(route3, 5);
  233. gettimeofday(&t2, NULL);
  234. elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
  235. elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
  236. fprintf(stderr, "smooth gridline based route took %f ms\n", elapsedTime);
  237. if(needJsonOutput) {
  238. json_update(route1s, route2s, n*n);
  239. }
  240. }
  241. break;
  242. case SDL_KEYDOWN :
  243. switch (e.key.keysym.sym) {
  244. case SDLK_p:
  245. view_points = !view_points;
  246. break;
  247. case SDLK_g:
  248. case SDLK_l:
  249. view_grid = !view_grid;
  250. break;
  251. case SDLK_w:
  252. view_waypoints = !view_waypoints;
  253. break;
  254. case SDLK_s:
  255. view_smoothed = !view_smoothed;
  256. break;
  257. case SDLK_j:
  258. view_json = !view_json;
  259. needJsonOutput = view_json;
  260. break;
  261. case SDLK_r:
  262. randomize(clusters, n, fac);
  263. break;
  264. case SDLK_BACKSPACE:
  265. set(clusters, n, safety_radius);
  266. break;
  267. case SDLK_q:
  268. quit = 1;
  269. break;
  270. case SDLK_UP:
  271. n++;
  272. clusters = realloc(clusters, sizeof(cluster_t) * n * n);
  273. fac = GLOBALS.WIDTH / (n + 1) * 0.3;
  274. set(clusters, n, safety_radius);
  275. break;
  276. case SDLK_DOWN:
  277. n--;
  278. clusters = realloc (clusters, sizeof(cluster_t) * n * n);
  279. fac = GLOBALS.WIDTH / (n + 1) * 0.3;
  280. set(clusters, n, safety_radius);
  281. break;
  282. case SDLK_PLUS:
  283. case SDLK_KP_PLUS:
  284. fac *= 1.1;
  285. fprintf(stderr, "fac: %f\n", fac);
  286. set(clusters, n, safety_radius);
  287. randomize(clusters, n, fac);
  288. break;
  289. case SDLK_MINUS:
  290. case SDLK_KP_MINUS:
  291. fac /= 1.1;
  292. fprintf(stderr, "fac: %f\n", fac);
  293. set(clusters, n, safety_radius);
  294. randomize(clusters, n, fac);
  295. break;
  296. default:
  297. needJsonOutput = 0;
  298. break;
  299. }
  300. break;
  301. case SDL_VIDEORESIZE:
  302. GLOBALS.WIDTH = e.resize.w;
  303. GLOBALS.HEIGHT = e.resize.h;
  304. sdl_screen_init();
  305. break;
  306. default :
  307. needJsonOutput = 0;
  308. break;
  309. }
  310. if(needJsonOutput) {
  311. json_output(clusters, n*n);
  312. }
  313. }
  314. free(clusters);
  315. return 0;
  316. }