gen_minimap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /* $Id: gen_minimap.c,v 1.23 2001/04/29 15:41:05 glop Exp $ */
  2. #include "client.h"
  3. #define OFFSET(X, Y) (((X) + (Y) * MINI_MAP_SIZE) * 4)
  4. #define RED(X,Y) (OFFSET(X, Y) + 0)
  5. #define GREEN(X,Y) (OFFSET(X, Y) + 1)
  6. #define BLUE(X,Y) (OFFSET(X, Y) + 2)
  7. #define ID(X,Y) (OFFSET(X, Y) + 3)
  8. #define RED_COLOR(map, id) ((map)->players[(id)]->colors[2])
  9. #define GREEN_COLOR(map, id) ((map)->players[(id)]->colors[1])
  10. #define BLUE_COLOR(map, id) ((map)->players[(id)]->colors[0])
  11. #define CONV_X(map, X) (((X) * MINI_MAP_SIZE) / ((map)->sizex + 0.1))
  12. #define CONV_Y(map, Y) (((Y) * MINI_MAP_SIZE) / ((map)->sizey + 0.1))
  13. static void mm_plot_point_ex(guchar *minimap, guchar id, guchar sat, int x, int y,
  14. guchar r, guchar g, guchar b)
  15. {
  16. int temp;
  17. if ((x < 0) || (x >= MINI_MAP_SIZE))
  18. return;
  19. if ((y < 0) || (y >= MINI_MAP_SIZE))
  20. return;
  21. if (minimap[ID(x, y)] == id)
  22. return;
  23. temp = minimap[RED(x,y)];
  24. if (temp < sat)
  25. {
  26. temp += r;
  27. if (temp > sat)
  28. temp = sat;
  29. minimap[RED(x,y)] = temp;
  30. }
  31. temp = minimap[GREEN(x,y)];
  32. if (temp < sat)
  33. {
  34. temp += g;
  35. if (temp > sat)
  36. temp = sat;
  37. minimap[GREEN(x,y)] = temp;
  38. }
  39. temp = minimap[BLUE(x,y)];
  40. if (temp < sat)
  41. {
  42. temp += b;
  43. if (temp > sat)
  44. temp = sat;
  45. minimap[BLUE(x,y)] = temp;
  46. }
  47. minimap[ID(x, y)] = id;
  48. }
  49. static void mm_plot_point(guchar *minimap, int x, int y,
  50. guchar r, guchar g, guchar b)
  51. {
  52. int temp;
  53. if ((x < 0) || (x >= MINI_MAP_SIZE))
  54. return;
  55. if ((y < 0) || (y >= MINI_MAP_SIZE))
  56. return;
  57. temp = minimap[RED(x,y)] + r;
  58. if (temp > 0xFF)
  59. temp = 0xFF;
  60. minimap[RED(x,y)] = temp;
  61. temp = minimap[GREEN(x,y)] + g;
  62. if (temp > 0xFF)
  63. temp = 0xFF;
  64. minimap[GREEN(x,y)] = temp;
  65. temp = minimap[BLUE(x,y)] + b;
  66. if (temp > 0xFF)
  67. temp = 0xFF;
  68. minimap[BLUE(x,y)] = temp;
  69. }
  70. static void mm_plot_line(guchar *minimap, int x1, int y1, int x2, int y2,
  71. guchar r, guchar g, guchar b)
  72. {
  73. float a;
  74. int diffx, diffy;
  75. int x, y;
  76. diffx = x1 - x2;
  77. diffy = y1 - y2;
  78. if (!diffx && !diffy)
  79. mm_plot_point(minimap, x1, y2, r, g, b);
  80. else
  81. {
  82. if (ABS(diffx) > ABS(diffy))
  83. {
  84. a = (float)diffy / diffx;
  85. if (x1 > x2)
  86. {
  87. x = x2;
  88. x2 = x1;
  89. x1 = x;
  90. y = y1;
  91. y1 = y2;
  92. y2 = y;
  93. }
  94. else
  95. x = x1;
  96. while (x != x2)
  97. {
  98. mm_plot_point(minimap, x, y1 + (x - x1) * a, r, g, b);
  99. x++;
  100. }
  101. }
  102. else
  103. {
  104. a = (float)diffx / diffy;
  105. if (y1 > y2)
  106. {
  107. y = y2;
  108. y2 = y1;
  109. y1 = y;
  110. x = x1;
  111. x1 = x2;
  112. x2 = x;
  113. }
  114. else
  115. y = y1;
  116. while (y != y2)
  117. {
  118. mm_plot_point(minimap, x1 + (y - y1) * a, y, r, g, b);
  119. y++;
  120. }
  121. }
  122. }
  123. }
  124. static float mm_rotate_x(float x, float y, float cs, float sn)
  125. {
  126. return cs * x + sn * y;
  127. }
  128. static float mm_rotate_y(float x, float y, float cs, float sn)
  129. {
  130. return cs * y - sn * x;
  131. }
  132. static int mm_distance(int x1, int y1, int x2, int y2)
  133. {
  134. return (SQR(x2 - x1) + SQR(y2 - y1));
  135. }
  136. static void mm_plot_triangle(guchar *minimap, guchar id, guchar sat,
  137. int x1, int y1, int x2, int y2, int x3, int y3,
  138. int dist, guchar cr, guchar cg, guchar cb)
  139. {
  140. int swap;
  141. float delta1, delta2, delta3;
  142. float xa, xb;
  143. int x, y;
  144. int memx = x1, memy = y1;
  145. if (y1 > y2)
  146. {
  147. swap = x1;
  148. x1 = x2;
  149. x2 = swap;
  150. swap = y1;
  151. y1 = y2;
  152. y2 = swap;
  153. }
  154. if (y1 > y3)
  155. {
  156. swap = x3;
  157. x3 = x1;
  158. x1 = swap;
  159. swap = y1;
  160. y1 = y3;
  161. y3 = swap;
  162. }
  163. if (y2 > y3)
  164. {
  165. swap = x3;
  166. x3 = x2;
  167. x2 = swap;
  168. swap = y3;
  169. y3 = y2;
  170. y2 = swap;
  171. }
  172. /* determination des coefficients directeurs */
  173. if (y1 != y3)
  174. delta1 = ((float)x1-x3)/(y1-y3);
  175. else
  176. delta1 = 0;
  177. if (y1 != y2)
  178. delta2 = ((float)x2-x1)/(y2-y1);
  179. else
  180. delta2 = 0;
  181. if (y2 != y3)
  182. delta3 = ((float)x3-x2)/(y3-y2);
  183. else
  184. delta3 = 0;
  185. /* PremiŠre partie du triangle ( tracage des section horizontale) */
  186. xa = x1;
  187. xb = x1;
  188. if (y1 != y2)
  189. {
  190. if (delta1 < delta2)
  191. for (y = y1; y < y2; y++)
  192. {
  193. xa = xa + delta1;
  194. xb = xb + delta2;
  195. for (x = xa; x < xb; x++)
  196. if (mm_distance(memx, memy, x, y) <= dist)
  197. mm_plot_point_ex(minimap, id, sat, x, y, cr, cg, cb);
  198. }
  199. else
  200. for (y = y1; y < y2; y++)
  201. {
  202. xa = xa + delta1;
  203. xb = xb + delta2;
  204. for (x = xb; x < xa; x++)
  205. if (mm_distance(memx, memy, x, y) <= dist)
  206. mm_plot_point_ex(minimap, id, sat, x, y, cr, cg, cb);
  207. }
  208. }
  209. else
  210. xb = x2;
  211. /* Deuxieme partie du triangle ( tracage des section horizontale) */
  212. if (y2 != y3)
  213. {
  214. if (delta3 < delta1)
  215. for (y = y2; y < y3; y++)
  216. {
  217. xa = xa + delta1;
  218. xb = xb + delta3;
  219. for (x = xa; x < xb; x++)
  220. if (mm_distance(memx, memy, x, y) <= dist)
  221. mm_plot_point_ex(minimap, id, sat, x, y, cr, cg, cb);
  222. }
  223. else
  224. for (y = y2; y < y3; y++)
  225. {
  226. xa = xa + delta1;
  227. xb = xb + delta3;
  228. for (x = xb; x < xa; x++)
  229. if (mm_distance(memx, memy, x, y) <= dist)
  230. mm_plot_point_ex(minimap, id, sat, x, y, cr, cg, cb);
  231. }
  232. }
  233. }
  234. static void mm_plot_cone(guchar *minimap, guchar id, guchar sat,
  235. float x1, float y1, float x2, float y2,
  236. float angle, guchar r, guchar g, guchar b)
  237. {
  238. float cs, sn, csi;
  239. float x, y, xc, xd, yc, yd;
  240. gboolean call_sub = FALSE;
  241. x = x2 - x1;
  242. y = y2 - y1;
  243. if (angle > M_PI_2)
  244. {
  245. call_sub = TRUE;
  246. angle /= 2;
  247. }
  248. cs = cos(angle / 2);
  249. sn = sin(angle / 2);
  250. xc = mm_rotate_x(x, y, cs, sn);
  251. xd = mm_rotate_x(x, y, cs, -sn);
  252. yc = mm_rotate_y(x, y, cs, sn);
  253. yd = mm_rotate_y(x, y, cs, -sn);
  254. if (call_sub)
  255. {
  256. mm_plot_cone(minimap, id, sat, x1, y1, xc + x1, yc + y1, angle, r, g, b);
  257. mm_plot_cone(minimap, id, sat, x1, y1, xd + x1, yd + y1, angle, r, g, b);
  258. return;
  259. }
  260. csi = 1 / cs;
  261. xc = xc * csi + x1;
  262. xd = xd * csi + x1;
  263. yc = yc * csi + y1;
  264. yd = yd * csi + y1;
  265. mm_plot_triangle(minimap, id, sat, x1, y1, xc, yc, xd, yd,
  266. mm_distance(x1, y1, x2, y2), r, g, b);
  267. }
  268. static void mm_plot_r4d2(const map_t *map, obj_t *obj, guchar *minimap)
  269. {
  270. int x = CONV_X(map, obj->posx);
  271. int y = CONV_Y(map, obj->posy);
  272. guchar *couleurs;
  273. if ((obj->team_id == 0) || (obj->team_id > map->nb_players))
  274. return;
  275. couleurs = map->players[obj->team_id]->colors;
  276. mm_plot_point(minimap, x, y,
  277. couleurs[2],
  278. couleurs[1],
  279. couleurs[0]);
  280. mm_plot_point(minimap, x+1, y,
  281. couleurs[2],
  282. couleurs[1],
  283. couleurs[0]);
  284. mm_plot_point(minimap, x, y+1,
  285. couleurs[2],
  286. couleurs[1],
  287. couleurs[0]);
  288. mm_plot_point(minimap, x-1, y,
  289. couleurs[2],
  290. couleurs[1],
  291. couleurs[0]);
  292. mm_plot_point(minimap, x, y-1,
  293. couleurs[2],
  294. couleurs[1],
  295. couleurs[0]);
  296. }
  297. static void mm_plot_akx(const map_t *map, obj_t *obj, guchar *minimap)
  298. {
  299. int id = obj->team_id;
  300. int x, y, x2, y2;
  301. int dx, dy;
  302. x = CONV_X(map, obj->posx);
  303. y = CONV_Y(map, obj->posy);
  304. x2 = CONV_X(map, obj->tx);
  305. y2 = CONV_Y(map, obj->ty);
  306. if (id > map->nb_players)
  307. id = 0;
  308. mm_plot_point(minimap, x, y, 0xFF, 0xFF, 0xFF);
  309. for (dx = -2; dx <= 2; dx++)
  310. for (dy = -2; dy <= 2; dy++)
  311. mm_plot_point(minimap, x + dx, y + dy,
  312. map->players[id]->colors[2],
  313. map->players[id]->colors[1],
  314. map->players[id]->colors[0]);
  315. /* affichage pulse */
  316. if (obj->action == act_akx_pulse)
  317. mm_plot_cone(minimap, 1+(guchar)obj->id, PULSE_SAT, x, y, x2, y2,
  318. obj->angle,
  319. map->players[id]->colors[2] / DIVID_PULSE_MINI,
  320. map->players[id]->colors[1] / DIVID_PULSE_MINI,
  321. map->players[id]->colors[0] / DIVID_PULSE_MINI);
  322. /* affichage link */
  323. if (obj->action == act_akx_link)
  324. mm_plot_line(minimap, x, y,
  325. CONV_X(map, map->objects[obj->target]->posx),
  326. CONV_Y(map, map->objects[obj->target]->posy),
  327. map->players[id]->colors[2],
  328. map->players[id]->colors[1],
  329. map->players[id]->colors[0]);
  330. }
  331. /* Zone de la vue principale */
  332. static void mm_plot_rectangle(guchar *minimap, const conf_t *conf)
  333. {
  334. int x1, y1, x2, y2;
  335. float ratiox, ratioy;
  336. int y, l, *buf;
  337. ratiox = MINI_MAP_SIZE / (conf->map->sizex * conf->big_zoom);
  338. ratioy = MINI_MAP_SIZE / (conf->map->sizey * conf->big_zoom);
  339. x1 = conf->big_ofs_x * ratiox;
  340. y1 = conf->big_ofs_y * ratioy;
  341. x2 = x1 + MAP_SIZE * ratiox;
  342. y2 = y1 + MAP_SIZE * ratioy;
  343. x1 = CLAMP(x1, 0, MINI_MAP_SIZE - 1);
  344. x2 = CLAMP(x2, 0, MINI_MAP_SIZE - 1);
  345. y1 = CLAMP(y1, 0, MINI_MAP_SIZE - 1);
  346. y2 = CLAMP(y2, 0, MINI_MAP_SIZE - 1);
  347. buf = (void *) minimap;
  348. memset(buf + x1 + y1 * MINI_MAP_SIZE, 255, (x2 - x1) * 4);
  349. memset(buf + x1 + y2 * MINI_MAP_SIZE, 255, (x2 - x1) * 4);
  350. memset(&l, 255, 4);
  351. for (y = y1 + 1; y < y2; y++)
  352. {
  353. buf[x1 + y * MINI_MAP_SIZE] = l;
  354. buf[x2 + y * MINI_MAP_SIZE] = l;
  355. }
  356. }
  357. guchar *gen_minimap(const conf_t *conf, gboolean force)
  358. {
  359. static guchar *minimap = NULL;
  360. int cpt;
  361. obj_t *obj;
  362. if (minimap == NULL)
  363. {
  364. minimap = g_malloc(4 * SQR(MINI_MAP_SIZE));
  365. bzero(minimap, SQR(MINI_MAP_SIZE) * 4);
  366. }
  367. if (!force)
  368. return minimap;
  369. if (conf->map == NULL)
  370. return minimap;
  371. bzero(minimap, SQR(MINI_MAP_SIZE) * 4);
  372. for (cpt = 0; cpt < conf->map->nb_objects; cpt++)
  373. {
  374. obj = conf->map->objects[cpt];
  375. switch (obj->type)
  376. {
  377. case obj_r4d2 :
  378. mm_plot_r4d2(conf->map, obj, minimap);
  379. break;
  380. case obj_akx :
  381. mm_plot_akx(conf->map, obj, minimap);
  382. break;
  383. }
  384. }
  385. mm_plot_rectangle(minimap, conf);
  386. return minimap;
  387. }
  388. static guchar my_creneau(int val)
  389. {
  390. if (val >= 0)
  391. return CLAMP((120 - val) * 0xFF / 120, 0, 0xFF);
  392. else
  393. return CLAMP((120 + val) * 0xFF / 120, 0, 0xFF);
  394. }
  395. void gen_colors(int id, int nbr, player_t *play)
  396. {
  397. int angle;
  398. angle = (360 * id) / nbr; /* position => angle dans spectre */
  399. if (angle > 180)
  400. angle = angle - 360;
  401. play->colors[2] = my_creneau(angle);
  402. play->colors[1] = my_creneau(angle - 120);
  403. play->colors[0] = my_creneau(angle + 120);
  404. play->gdkcol = g_malloc(sizeof(*(play->gdkcol)));
  405. pl_make_color(play->gdkcol,
  406. play->colors[2], play->colors[1], play->colors[0]);
  407. }