draw_states.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include "draw_states.h"
  2. #include "fxlib.h"
  3. #include "fixed.h"
  4. #include <stdio.h>
  5. // static functions
  6. static void fillBackground(Game_Data *data);
  7. static void drawPlayer(Game_Data *data, int player_angle);
  8. static void drawPolygon(Game_Data *data, int nb_lines, Line_Transition line_transition);
  9. static void drawDiagonals(Game_Data *data, int nb_lines, Line_Transition line_transition);
  10. static void drawHud(Game_Data *data);
  11. static void drawChrono(Game_Data *data);
  12. static void drawStep(Game_Data *data);
  13. static unsigned int length_of_print_string(unsigned char* txt);
  14. static void drawTopLeftCornerText(unsigned char* txt, unsigned char isReversed);
  15. static void drawTopRightCornerText(unsigned char* txt, unsigned char isReversed);
  16. static void drawBottomLeftCornerText(unsigned char* txt, unsigned char isReversed);
  17. static void drawBottomRightCornerText(unsigned char* txt, unsigned char isReversed);
  18. static const unsigned char title_spr[] = {0x07, 0xF6, 0x1B, 0xFD, 0xFE, 0xFE, 0x00, 0x00, 0x0F, 0xF6, 0x1B, 0xFD, 0xFE, 0xFF, 0x00, 0x00, 0x0C, 0x06, 0x1B, 0x0D, 0x80, 0xC3, 0x00, 0x00, 0x0F, 0xF6, 0x1B, 0x0D, 0xFE, 0xC3, 0x00, 0x00, 0x0F, 0xF6, 0x1B, 0xFD, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x36, 0x1B, 0xF9, 0x80, 0xFF, 0x00, 0x00, 0x0F, 0xF7, 0xFB, 0x01, 0xFE, 0xC3, 0x00, 0x00, 0x0F, 0xE3, 0xFB, 0x00, 0xFE, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x7F, 0xB0, 0xCF, 0xEF, 0xF3, 0xFB, 0xF8, 0xC3, 0x7F, 0xB0, 0xDF, 0xEF, 0xF7, 0xFB, 0xFC, 0xC3, 0x60, 0x30, 0xD8, 0x6C, 0x06, 0x1B, 0x0C, 0xFF, 0x7F, 0xBF, 0xD8, 0x6C, 0x36, 0x1B, 0x0C, 0xFF, 0x7F, 0x9F, 0x9F, 0xEC, 0x36, 0x1B, 0x0C, 0xC3, 0x60, 0x30, 0xDF, 0xEC, 0x36, 0x1B, 0x0C, 0xC3, 0x7F, 0xB0, 0xD8, 0x6F, 0xF7, 0xFB, 0x0C, 0xC3, 0x3F, 0xB0, 0xD8, 0x6F, 0xE7, 0xF3, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x9F, 0xCF, 0xEF, 0xF3, 0xF8, 0x00, 0x00, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xF8, 0x00, 0x00, 0x60, 0x30, 0xD8, 0x01, 0x86, 0x18, 0x00, 0x00, 0x60, 0x30, 0xDF, 0xE1, 0x86, 0x18, 0x00, 0x00, 0x60, 0x3F, 0xDF, 0xE1, 0x86, 0x18, 0x00, 0x00, 0x60, 0x3F, 0xC0, 0x61, 0x86, 0x18, 0x00, 0x00, 0x7F, 0xB0, 0xDF, 0xEF, 0xF7, 0xF8, 0x00, 0x00, 0x3F, 0xB0, 0xDF, 0xCF, 0xF7, 0xF0, 0x00};
  19. static const unsigned char hex_border_top_left[8] = {0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80};
  20. static const unsigned char hex_border_top_right[8] ={0x1F, 0x1F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03};
  21. static const unsigned char hex_border_bottom_left[8] = {0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0};
  22. static const unsigned char hex_border_bottom_right[8] ={0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1F, 0x1F};
  23. static const unsigned char hex_border_top_left_rev[8] = {0x0F, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F};
  24. static const unsigned char hex_border_top_right_rev[8] ={0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC};
  25. static const unsigned char hex_border_bottom_left_rev[8] = {0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F};
  26. static const unsigned char hex_border_bottom_right_rev[8] ={0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0};
  27. void draw_game(Game_Data *data)
  28. {
  29. fillBackground(data);
  30. // draw the player and the lines
  31. drawPlayer(data, data->player_angle);
  32. drawPolygon(data, data->nb_lines, data->line_transition);
  33. drawDiagonals(data, data->nb_lines, data->line_transition);
  34. // showing the walls
  35. if(data->list != NULL)
  36. drawWalls(data->list, data, data->nb_lines, data->line_transition);
  37. drawHud(data);
  38. }
  39. void draw_title(Game_Data *data)
  40. {
  41. fillBackground(data);
  42. ML_bmp_or(title_spr, 12, (64-26)/2, 62, 26);
  43. drawPolygon(data, data->nb_lines, data->line_transition);
  44. drawDiagonals(data, data->nb_lines, data->line_transition);
  45. drawBottomLeftCornerText("Press Shift", data->are_colors_reversed);
  46. drawTopRightCornerText("By Eiyeron & Adbook", data->are_colors_reversed);
  47. }
  48. void draw_menu(Game_Data *data)
  49. {
  50. fillBackground(data);
  51. drawPolygon(data, data->nb_lines, data->line_transition);
  52. drawDiagonals(data, data->nb_lines, data->line_transition);
  53. drawTopRightCornerText(data->entry_difficulties[data->current_entry - 1], data->are_colors_reversed);
  54. if(data->current_entry > 3) {
  55. // Hyper Mode
  56. drawBottomRightCornerText("Hyper Mode", data->are_colors_reversed);
  57. }
  58. }
  59. void draw_game_over(Game_Data *data)
  60. {
  61. unsigned char time_text[32] = "";
  62. sprintf(time_text, "%.2f", data->chrono_time);
  63. fillBackground(data);
  64. drawPolygon(data, data->nb_lines, data->line_transition);
  65. drawDiagonals(data, data->nb_lines, data->line_transition);
  66. drawTopLeftCornerText(time_text, data->are_colors_reversed);
  67. drawBottomLeftCornerText("Press Shift to retry", data->are_colors_reversed);
  68. }
  69. static void fillBackground(Game_Data *data) {
  70. if(data->are_colors_reversed) {
  71. int i, end, *pointer_long, vram;
  72. char *pointer_byte;
  73. vram = (int)ML_vram_adress();
  74. end = 4-vram&3;
  75. pointer_byte = (char*)vram;
  76. for(i=0 ; i<end ; i++) pointer_byte[i] = 0xFF;
  77. pointer_long = (int*) (vram+end);
  78. for(i=0 ; i<255 ; i++) pointer_long[i] = 0xFFFFFFFF;
  79. pointer_byte += 1020+end;
  80. end = vram&3;
  81. for(i=0 ; i<end ; i++) pointer_byte[i] = 0xFF;
  82. } else {
  83. ML_clear_vram();
  84. }
  85. }
  86. static void drawChrono(Game_Data *data) {
  87. unsigned char time_text[32] = "";
  88. sprintf(time_text, "%.2f", data->chrono_time);
  89. if(data->chrono_time < 60) {
  90. // Drawing the text with the little progress bar. As I offset the text,
  91. // I need to remake the whole routine.
  92. ML_Color drawing_color = data->are_colors_reversed ? WHITE : BLACK;
  93. unsigned int text_color = data->are_colors_reversed ? MINI_OVER : MINI_REV;
  94. unsigned short length_of_time, length_of_time_line;
  95. length_of_time = strlen(time_text);
  96. length_of_time_line = 4 * length_of_time;
  97. PrintMini(0, 0, time_text, text_color);
  98. ML_horizontal_line(6, 0, (data->chrono_time/60.) * (length_of_time_line - 2), drawing_color);
  99. ML_horizontal_line(7, 0, length_of_time_line - 1, drawing_color);
  100. if(!data->are_colors_reversed) {
  101. ML_bmp_8_or(hex_border_top_left, length_of_time_line, 0);
  102. } else {
  103. ML_bmp_8_and(hex_border_top_left_rev, length_of_time_line, 0);
  104. }
  105. }
  106. else {
  107. drawTopLeftCornerText(time_text, data->are_colors_reversed);
  108. }
  109. }
  110. static void drawStep(Game_Data *data) {
  111. unsigned char *step_text[6] = {
  112. "Point",
  113. "Line",
  114. "Triangle",
  115. "Square",
  116. "Pentagon",
  117. "Hexagon"
  118. };
  119. unsigned short step_time[5] = {
  120. 10,
  121. 20,
  122. 30,
  123. 45,
  124. 60
  125. };
  126. unsigned short current_step, i;
  127. current_step = 5;
  128. for(i = 0; i < 5; i++) {
  129. if(data->chrono_time < step_time[i]) {
  130. current_step = i;
  131. break;
  132. }
  133. }
  134. drawTopRightCornerText(step_text[current_step], data->are_colors_reversed);
  135. }
  136. static void drawHud(Game_Data *data) {
  137. drawChrono(data);
  138. drawStep(data);
  139. }
  140. static void drawPolygon(Game_Data *data, int nb_lines, Line_Transition line_transition) {
  141. int x[32];
  142. int y[32];
  143. int i = 0;
  144. int angle = 0;
  145. Camera* cam= &data->cam;
  146. ML_Color drawing_color = data->are_colors_reversed ? WHITE : BLACK;
  147. float tmp_angle = 0.0;
  148. float transition_angle = 0.0;
  149. float delta_angle = 0.0;
  150. if(line_transition.delta_nb_lines == 1)
  151. nb_lines ++;
  152. if(line_transition.counter_start != 0)
  153. transition_angle = (360.0 / (float)nb_lines) * ((float)line_transition.counter / (float)line_transition.counter_start);
  154. delta_angle = 360.0/nb_lines;
  155. do
  156. {
  157. // TODO : use fixed for only two trig calls?
  158. x[i] = (8. + cam->zoom)*cos(PI * (tmp_angle + cam->angle)/180.) + cam->cX;
  159. y[i] = (8. + cam->zoom)*sin(PI * (tmp_angle + cam->angle)/180.) + cam->cY;
  160. i++;
  161. switch(line_transition.delta_nb_lines)
  162. {
  163. case 0:
  164. tmp_angle += delta_angle;
  165. break;
  166. case 1:
  167. if(i < nb_lines)
  168. tmp_angle += (360 - (delta_angle - transition_angle)) / (nb_lines - 1);
  169. else
  170. tmp_angle += delta_angle - transition_angle;
  171. break;
  172. case -1:
  173. if(i < nb_lines)
  174. tmp_angle += (360 - transition_angle) / (nb_lines - 1);
  175. else
  176. tmp_angle = transition_angle;
  177. break;
  178. }
  179. }while(i <= nb_lines);
  180. // draw the aforementionned circle, depending on the camera's center
  181. // ML_filled_circle(cam.cX, cam.cY, 6, BLACK);
  182. ML_polygone(x, y, nb_lines, drawing_color);
  183. // draw the player. At such a low scale, it was impossible to draw a rotating triangle, so its a radius 1 circle instead.
  184. // TODO : Replace it for a quick sprite blit, or unwrapped ML_pixel procedure.
  185. }
  186. // draws the player
  187. // at first, was supposed to draw an hexagon in the center, plus a triangle to show the player,
  188. // but the hexagon was not visible, and it was a pixel mess, so we're showing a circle instead.
  189. // there is still for code to calculate the vertices of the hexagon, in case we want to change that again
  190. static void drawPlayer(Game_Data *data, int player_angle)
  191. {
  192. ML_Color drawing_color = data->are_colors_reversed ? WHITE : BLACK;
  193. ML_filled_circle((9. + data->cam.zoom)*cos( PI*(player_angle + data->cam.angle)/180) + data->cam.cX, (9. + data->cam.zoom)*sin( PI*(player_angle+data->cam.angle)/180) + data->cam.cY, 1, drawing_color);
  194. }
  195. // draws one of the three rotating lines
  196. static void drawDiagonals(Game_Data *data, int nb_lines, Line_Transition line_transition)
  197. {
  198. fix tmp_angle = FIX(data->cam.angle);
  199. int i = 0;
  200. fix x1 = 0, y1 = 0, x2 = 0, y2 = 0;
  201. fix delta_angle = 0;
  202. fix coeff = 0;
  203. fix transition_angle = 0;
  204. ML_Color drawing_color = data->are_colors_reversed ? WHITE : BLACK;
  205. delta_angle = fdiv(FIX(360), FIX(nb_lines));
  206. if(line_transition.delta_nb_lines == 1)
  207. nb_lines ++;
  208. if(line_transition.counter_start != 0)
  209. coeff = fdiv(FIX(line_transition.counter), FIX(line_transition.counter_start));
  210. transition_angle = fmul(delta_angle, coeff);
  211. do{
  212. x1 = fmul(FIX(9) + ftofix(data->cam.zoom), fcos(tmp_angle));
  213. y1 = fmul(FIX(9) + ftofix(data->cam.zoom), fsin(tmp_angle));
  214. x2 = fmul(fcos(tmp_angle), FIX(128));
  215. y2 = fmul(fsin(tmp_angle), FIX(128));
  216. ML_line(UNFIX(x1) + data->cam.cX, UNFIX(y1) + data->cam.cY, UNFIX(x2) + data->cam.cX, UNFIX(y2) + data->cam.cY, drawing_color);
  217. i++;
  218. switch(line_transition.delta_nb_lines){
  219. case 0:
  220. tmp_angle += fdiv(FIX(360), FIX(nb_lines));
  221. break;
  222. case 1:
  223. if(i < nb_lines - 1)
  224. {
  225. tmp_angle += fdiv(FIX(360) - (delta_angle - transition_angle), FIX(nb_lines - 1));
  226. }else{
  227. tmp_angle += delta_angle - transition_angle;
  228. }
  229. break;
  230. case -1:
  231. if(i < nb_lines - 1)
  232. {
  233. tmp_angle += fdiv(FIX(360) - transition_angle, FIX(nb_lines - 1));
  234. }else{
  235. tmp_angle += transition_angle;
  236. }
  237. break;
  238. }
  239. if(tmp_angle >= FIX(360)) tmp_angle = tmp_angle - FIX(359);
  240. }while(i < nb_lines);
  241. }
  242. static unsigned int length_of_print_string(unsigned char* txt) {
  243. // TODO : define
  244. unsigned int text_length = 0;
  245. unsigned int i;
  246. unsigned int current_char_length = 0;
  247. for(i = 0; i < strlen(txt); i++) {
  248. switch(txt[i]) {
  249. // upper case
  250. case 'K':
  251. case 'M':
  252. case 'N':
  253. case 'Q':
  254. case 'W':
  255. current_char_length = 6;
  256. break;
  257. // lower case
  258. case 'i':
  259. current_char_length = 2;
  260. break;
  261. case 'n':
  262. case 'r':
  263. current_char_length = 5;
  264. break;
  265. case 'm':
  266. case 'w':
  267. current_char_length = 6;
  268. break;
  269. case '&':
  270. current_char_length = 5;
  271. break;
  272. case '[':
  273. case ']':
  274. current_char_length = 3;
  275. break;
  276. //
  277. //
  278. default:
  279. current_char_length = 4;
  280. break;
  281. }
  282. text_length += current_char_length;
  283. }
  284. return text_length;
  285. }
  286. static void drawTopLeftCornerText(unsigned char* txt, unsigned char isReversed) {
  287. ML_Color drawing_color = isReversed ? WHITE : BLACK;
  288. unsigned int text_color = isReversed ? MINI_OVER : MINI_REV;
  289. unsigned int text_length = length_of_print_string(txt);
  290. if(!isReversed) {
  291. ML_bmp_8_or(hex_border_top_left, text_length, 0);
  292. } else {
  293. ML_bmp_8_and(hex_border_top_left_rev, text_length, 0);
  294. }
  295. PrintMini(0, 1, txt, text_color);
  296. ML_horizontal_line(7, 0, text_length, drawing_color);
  297. }
  298. static void drawTopRightCornerText(unsigned char* txt, unsigned char isReversed) {
  299. ML_Color drawing_color = isReversed ? WHITE : BLACK;
  300. unsigned int text_color = isReversed ? MINI_OVER : MINI_REV;
  301. int text_length = length_of_print_string(txt);
  302. int xPosition = 128 - text_length;
  303. if(!isReversed) {
  304. ML_bmp_8_or(hex_border_top_right, xPosition - 8, 0);
  305. } else {
  306. ML_bmp_8_and(hex_border_top_right_rev, xPosition - 8, 0);
  307. }
  308. PrintMini(xPosition, 1, txt, text_color);
  309. ML_horizontal_line(7, xPosition, 127, drawing_color);
  310. }
  311. static void drawBottomLeftCornerText(unsigned char* txt, unsigned char isReversed) {
  312. ML_Color drawing_color = isReversed ? WHITE : BLACK;
  313. unsigned int text_length = length_of_print_string(txt);
  314. unsigned int text_color = isReversed ? MINI_OVER : MINI_REV;
  315. if(!isReversed) {
  316. ML_bmp_8_or(hex_border_bottom_left, text_length - 1, 56);
  317. } else {
  318. ML_bmp_8_and(hex_border_bottom_left_rev, text_length - 1, 56);
  319. }
  320. PrintMini(0, 57, txt, text_color);
  321. ML_horizontal_line(63, 0, text_length, drawing_color);
  322. }
  323. static void drawBottomRightCornerText(unsigned char* txt, unsigned char isReversed) {
  324. ML_Color drawing_color = isReversed ? WHITE : BLACK;
  325. unsigned int text_color = isReversed ? MINI_OVER : MINI_REV;
  326. int text_length = length_of_print_string(txt);
  327. int xPosition = 128 - text_length;
  328. if(!isReversed) {
  329. ML_bmp_8_or(hex_border_bottom_right, xPosition - 8, 56);
  330. } else {
  331. ML_bmp_8_and(hex_border_bottom_right_rev, xPosition - 8, 56);
  332. }
  333. ML_horizontal_line(63, xPosition, 127, drawing_color);
  334. PrintMini(xPosition, 57, txt, text_color);
  335. }