You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

536 lines
15 KiB

  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include "common.h"
  4. static void draw_bomb( int x, int y, int vx, int vy );
  5. static void draw_nuke( int x, int y, int frame );
  6. static void draw_beam( int x, int y, int frame );
  7. static void draw_circle( int x, int y, int r, char c );
  8. void init_weapons( game *g, weapons *wp )
  9. {
  10. int i;
  11. for( i = 0; i < WEAPONS; i++ )
  12. {
  13. wp->type[i] = WEAPON_NONE;
  14. }
  15. }
  16. void draw_weapons( game *g, weapons *wp )
  17. {
  18. int i;
  19. for( i = 0; i < WEAPONS; i++ )
  20. {
  21. switch( wp->type[i] )
  22. {
  23. case WEAPON_LASER:
  24. gfx_color( WHITE );
  25. gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
  26. gfx_putchar( '|' );
  27. gfx_color( CYAN );
  28. gfx_goto( wp->x[i] >> 4, (wp->y[i] >> 4) + 1 );
  29. gfx_putchar( '|' );
  30. break;
  31. case WEAPON_SEEKER:
  32. gfx_color( CYAN );
  33. gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
  34. gfx_putchar( '.' );
  35. gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
  36. gfx_putchar( 'o' );
  37. gfx_color( WHITE );
  38. gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
  39. gfx_putchar( '@' );
  40. break;
  41. case WEAPON_BOMB:
  42. gfx_color( GRAY );
  43. gfx_goto( (wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4 );
  44. gfx_putchar( '.' );
  45. gfx_goto( (wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4 );
  46. gfx_putchar( '.' );
  47. gfx_goto( (wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4 );
  48. gfx_putchar( '.' );
  49. gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
  50. gfx_putchar( '.' );
  51. gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
  52. gfx_putchar( '.' );
  53. draw_bomb( wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i] );
  54. break;
  55. case WEAPON_BEAM:
  56. draw_beam( wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i] );
  57. break;
  58. case WEAPON_NUKE:
  59. draw_nuke( wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i] );
  60. break;
  61. case WEAPON_NONE:
  62. break;
  63. }
  64. }
  65. }
  66. void update_weapons( game *g, weapons *wp )
  67. {
  68. int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
  69. for( i = 0; i < WEAPONS; i++ )
  70. {
  71. switch( wp->type[i] )
  72. {
  73. case WEAPON_LASER:
  74. wp->x[i] += wp->vx[i];
  75. wp->y[i] += wp->vy[i];
  76. if( wp->y[i] < 0 )
  77. {
  78. wp->type[i] = WEAPON_NONE;
  79. }
  80. break;
  81. case WEAPON_BOMB:
  82. case WEAPON_SEEKER:
  83. /* Update tail */
  84. wp->x3[i] = wp->x2[i];
  85. wp->y3[i] = wp->y2[i];
  86. wp->x2[i] = wp->x[i];
  87. wp->y2[i] = wp->y[i];
  88. wp->x[i] += wp->vx[i];
  89. wp->y[i] += wp->vy[i];
  90. if( wp->y[i] < 0 )
  91. {
  92. wp->type[i] = WEAPON_NONE;
  93. break;
  94. }
  95. if( wp->n[i] < 0 )
  96. {
  97. /* Stop updating direction */
  98. break;
  99. }
  100. wp->n[i]--;
  101. /* Estimate our position in 2 frames */
  102. xnew = wp->x[i] + 4 * wp->vx[i];
  103. ynew = wp->y[i] + 4 * wp->vy[i];
  104. xmin = xnew;
  105. ymin = - (g->h << 4);
  106. dist = (xnew - xmin) * (xnew - xmin)
  107. + 4 * (ynew - ymin) * (ynew - ymin);
  108. /* Find the nearest alien */
  109. for( j = 0; j < ALIENS; j++ )
  110. {
  111. if( g->al->type[j] != ALIEN_NONE )
  112. {
  113. int alx = g->al->x[j] << 4;
  114. int aly = g->al->y[j] << 4;
  115. int new = (xnew - alx) * (xnew - alx)
  116. + 4 * (ynew - aly) * (ynew - aly);
  117. if( new <= dist )
  118. {
  119. dist = new;
  120. xmin = alx;
  121. ymin = aly;
  122. }
  123. }
  124. }
  125. /* Find our new direction */
  126. dx = xmin - wp->x[i];
  127. dy = ymin - wp->y[i];
  128. /* Normalize and update speed */
  129. wp->vx[i] = (7 * wp->vx[i]
  130. + (dx * 48) / sqrt(dx*dx+dy*dy) ) / 8;
  131. wp->vy[i] = (7 * wp->vy[i]
  132. + (dy * 24) / sqrt(dx*dx+dy*dy) ) / 8;
  133. break;
  134. case WEAPON_BEAM:
  135. wp->x[i] = (g->p->x + 2) << 4;
  136. wp->y[i] = g->p->y << 4;
  137. wp->n[i]--;
  138. if( wp->n[i] < 0 )
  139. {
  140. wp->type[i] = WEAPON_NONE;
  141. }
  142. break;
  143. case WEAPON_NUKE:
  144. wp->n[i]--;
  145. if( wp->n[i] < 0 )
  146. {
  147. wp->type[i] = WEAPON_NONE;
  148. }
  149. break;
  150. case WEAPON_NONE:
  151. break;
  152. }
  153. }
  154. }
  155. void add_weapon( game *g, weapons *wp, int x, int y, int vx, int vy, int type )
  156. {
  157. int i;
  158. for( i = 0; i < WEAPONS; i++ )
  159. {
  160. if( wp->type[i] == WEAPON_NONE )
  161. {
  162. wp->x[i] = x;
  163. wp->y[i] = y;
  164. wp->vx[i] = vx;
  165. wp->vy[i] = vy;
  166. wp->type[i] = type;
  167. switch( type )
  168. {
  169. case WEAPON_LASER:
  170. break;
  171. case WEAPON_SEEKER:
  172. case WEAPON_BOMB:
  173. wp->x2[i] = x;
  174. wp->y2[i] = y;
  175. wp->x3[i] = x;
  176. wp->y3[i] = y;
  177. wp->n[i] = 10;
  178. break;
  179. case WEAPON_BEAM:
  180. wp->n[i] = 25;
  181. break;
  182. case WEAPON_NUKE:
  183. wp->n[i] = 25;
  184. break;
  185. case WEAPON_NONE:
  186. break;
  187. }
  188. break;
  189. }
  190. }
  191. }
  192. static void draw_bomb( int x, int y, int vx, int vy )
  193. {
  194. vy *= 2;
  195. gfx_color( CYAN );
  196. if( vx > vy )
  197. {
  198. if( vx > -vy ) /* right quarter */
  199. {
  200. if( vy > vx/4 )
  201. {
  202. /* -1pi/6 */
  203. gfx_goto( x-4, y-1 );
  204. gfx_putstr( "/`-." );
  205. gfx_goto( x-4, y );
  206. gfx_putstr( "`-._\\" );
  207. gfx_goto( x, y+1 );
  208. gfx_putchar( '`' );
  209. }
  210. else if( vy < -vx/4 )
  211. {
  212. /* 1pi/6 */
  213. gfx_goto( x-1, y-1 );
  214. gfx_putstr( "_," );
  215. gfx_goto( x-4, y );
  216. gfx_putstr( ",-' /" );
  217. gfx_goto( x-4, y+1 );
  218. gfx_putstr( "\\,-'" );
  219. }
  220. else
  221. {
  222. /* 0pi/6 */
  223. gfx_goto( x-4, y-1 );
  224. gfx_putstr( "____" );
  225. gfx_goto( x-5, y );
  226. gfx_putstr( "|____>" );
  227. }
  228. }
  229. else /* top quarter */
  230. {
  231. if( vx > -vy/4 )
  232. {
  233. /* 2pi/6 */
  234. gfx_goto( x-1, y-1 );
  235. gfx_putstr( "_," );
  236. gfx_goto( x-2, y );
  237. gfx_putstr( "/ |" );
  238. gfx_goto( x-3, y+1 );
  239. gfx_putstr( "/ /" );
  240. gfx_goto( x-3, y+2 );
  241. gfx_putstr( "`'" );
  242. }
  243. else if( vx < vy/4 )
  244. {
  245. /* 4pi/6 */
  246. gfx_goto( x, y-1 );
  247. gfx_putstr( "._" );
  248. gfx_goto( x, y );
  249. gfx_putstr( "| \\" );
  250. gfx_goto( x+1, y+1 );
  251. gfx_putstr( "\\ \\" );
  252. gfx_goto( x+2, y+2 );
  253. gfx_putstr( "`'" );
  254. }
  255. else
  256. {
  257. /* 3pi/6 */
  258. gfx_goto( x-1, y );
  259. gfx_putstr( ",^." );
  260. gfx_goto( x-1, y+1 );
  261. gfx_putstr( "| |" );
  262. gfx_goto( x-1, y+2 );
  263. gfx_putstr( "|_|" );
  264. }
  265. }
  266. }
  267. else
  268. {
  269. if( vx > -vy ) /* bottom quarter */
  270. {
  271. if( vx > vy/4 )
  272. {
  273. /* -2pi/6 */
  274. gfx_goto( x-2, y-2 );
  275. gfx_putstr( ",." );
  276. gfx_goto( x-2, y-1 );
  277. gfx_putstr( "\\ \\" );
  278. gfx_goto( x-1, y );
  279. gfx_putstr( "\\_|" );
  280. }
  281. else if( vx < -vy/4 )
  282. {
  283. /* -4pi/6 */
  284. gfx_goto( x+1, y-2 );
  285. gfx_putstr( ",." );
  286. gfx_goto( x, y-1 );
  287. gfx_putstr( "/ /" );
  288. gfx_goto( x-1, y );
  289. gfx_putstr( "|_/" );
  290. }
  291. else
  292. {
  293. /* -3pi/6 */
  294. gfx_goto( x, y-3 );
  295. gfx_putchar( '_' );
  296. gfx_goto( x-1, y-2 );
  297. gfx_putstr( "| |" );
  298. gfx_goto( x-1, y-1 );
  299. gfx_putstr( "| |" );
  300. gfx_goto( x-1, y );
  301. gfx_putstr( "`v'" );
  302. }
  303. }
  304. else /* left quarter */
  305. {
  306. if( vy > -vx/4 )
  307. {
  308. /* -5pi/6 */
  309. gfx_goto( x+1, y-1 );
  310. gfx_putstr( ",-'\\" );
  311. gfx_goto( x, y );
  312. gfx_putstr( "/_,-'" );
  313. gfx_goto( x, y+1 );
  314. gfx_putchar( '\'' );
  315. }
  316. else if( vy < vx/4 )
  317. {
  318. /* 5pi/6 */
  319. gfx_goto( x, y-1 );
  320. gfx_putstr( "._" );
  321. gfx_goto( x, y );
  322. gfx_putstr( "\\ `-." );
  323. gfx_goto( x+1, y+1 );
  324. gfx_putstr( "`-./" );
  325. }
  326. else
  327. {
  328. /* 6pi/6 */
  329. gfx_goto( x+1, y-1 );
  330. gfx_putstr( "____" );
  331. gfx_goto( x, y );
  332. gfx_putstr( "<____|" );
  333. }
  334. }
  335. }
  336. }
  337. static void draw_beam( int x, int y, int frame )
  338. {
  339. int r = (29 - frame) * (29 - frame) / 8;
  340. int i;
  341. switch( frame )
  342. {
  343. case 24:
  344. gfx_color( WHITE );
  345. gfx_goto( x, y-3 );
  346. gfx_putstr( "__" );
  347. gfx_goto( x-1, y-2 );
  348. gfx_putchar( '\'' );
  349. gfx_goto( x+2, y-2 );
  350. gfx_putchar( '`' );
  351. break;
  352. case 23:
  353. gfx_color( CYAN );
  354. gfx_goto( x, y-3 );
  355. gfx_putstr( "__" );
  356. gfx_color( WHITE );
  357. gfx_goto( x-2, y-2 );
  358. gfx_putstr( "-'" );
  359. gfx_goto( x+2, y-2 );
  360. gfx_putstr( "`-" );
  361. break;
  362. case 22:
  363. gfx_color( CYAN );
  364. gfx_goto( x, y-3 );
  365. gfx_putstr( "__" );
  366. gfx_goto( x-1, y-2 );
  367. gfx_putchar( '\'' );
  368. gfx_goto( x+2, y-2 );
  369. gfx_putchar( '`' );
  370. gfx_color( WHITE );
  371. gfx_goto( x-3, y-2 );
  372. gfx_putstr( ",-" );
  373. gfx_goto( x+3, y-2 );
  374. gfx_putstr( "-." );
  375. break;
  376. case 21:
  377. gfx_color( CYAN );
  378. gfx_goto( x-1, y-3 );
  379. gfx_putstr( "____" );
  380. gfx_goto( x-2, y-2 );
  381. gfx_putchar( '\'' );
  382. gfx_goto( x+3, y-2 );
  383. gfx_putchar( '`' );
  384. gfx_color( WHITE );
  385. gfx_goto( x-4, y-2 );
  386. gfx_putstr( ",-" );
  387. gfx_goto( x+4, y-2 );
  388. gfx_putstr( "-." );
  389. break;
  390. case 20:
  391. gfx_color( WHITE );
  392. gfx_goto( x, y-3 );
  393. gfx_putstr( "%%" );
  394. gfx_goto( x-4, y-2 );
  395. gfx_putchar( ',' );
  396. gfx_goto( x+5, y-2 );
  397. gfx_putchar( '.' );
  398. gfx_color( CYAN );
  399. gfx_goto( x-1, y-3 );
  400. gfx_putchar( ':' );
  401. gfx_goto( x+2, y-3 );
  402. gfx_putchar( ':' );
  403. gfx_goto( x-3, y-2 );
  404. gfx_putstr( "-'" );
  405. gfx_goto( x+3, y-2 );
  406. gfx_putstr( "`-" );
  407. break;
  408. case 19:
  409. gfx_color( WHITE );
  410. gfx_goto( x, y-4 );
  411. gfx_putstr( "%%" );
  412. gfx_goto( x, y-3 );
  413. gfx_putstr( "##" );
  414. gfx_color( CYAN );
  415. gfx_goto( x-1, y-4 );
  416. gfx_putchar( ':' );
  417. gfx_goto( x+2, y-4 );
  418. gfx_putchar( ':' );
  419. gfx_goto( x-1, y-3 );
  420. gfx_putchar( '%' );
  421. gfx_goto( x+2, y-3 );
  422. gfx_putchar( '%' );
  423. gfx_goto( x-4, y-2 );
  424. gfx_putstr( ",-'" );
  425. gfx_goto( x+3, y-2 );
  426. gfx_putstr( "`-." );
  427. gfx_color( BLUE );
  428. gfx_goto( x-2, y-3 );
  429. gfx_putchar( ':' );
  430. gfx_goto( x+3, y-3 );
  431. gfx_putchar( ':' );
  432. break;
  433. case 18:
  434. default:
  435. r = (18 - frame) * (18 - frame);
  436. gfx_color( WHITE );
  437. gfx_goto( x-1, y-5-r );
  438. gfx_putstr( ":%%:" );
  439. gfx_goto( x-1, y-4-r );
  440. gfx_putstr( "%##%" );
  441. gfx_color( CYAN );
  442. gfx_goto( x-2, y-4-r );
  443. gfx_putchar( ':' );
  444. gfx_goto( x+3, y-4-r );
  445. gfx_putchar( ':' );
  446. gfx_goto( x-2, y-2 );
  447. gfx_putchar( '\'' );
  448. gfx_goto( x+3, y-2 );
  449. gfx_putchar( '`' );
  450. gfx_color( BLUE );
  451. gfx_goto( x-3, y-2 );
  452. gfx_putchar( ':' );
  453. gfx_goto( x+4, y-2 );
  454. gfx_putchar( ':' );
  455. for( i = 0; i <= r; i++ )
  456. {
  457. gfx_color( WHITE );
  458. gfx_goto( x-1, y-3-i );
  459. gfx_putstr( "####" );
  460. gfx_color( CYAN );
  461. gfx_goto( x-2, y-3-i );
  462. gfx_putchar( '%' );
  463. gfx_goto( x+3, y-3-i );
  464. gfx_putchar( '%' );
  465. gfx_color( BLUE );
  466. gfx_goto( x-3, y-3-i );
  467. gfx_putchar( ':' );
  468. gfx_goto( x+4, y-3-i );
  469. gfx_putchar( ':' );
  470. }
  471. break;
  472. }
  473. }
  474. static void draw_nuke( int x, int y, int frame )
  475. {
  476. int r = (29 - frame) * (29 - frame) / 8;
  477. /* Lots of duplicate pixels, but we don't care */
  478. gfx_color( BLUE );
  479. draw_circle( x, y, r++, ':' );
  480. gfx_color( CYAN );
  481. draw_circle( x, y, r++, '%' );
  482. gfx_color( WHITE );
  483. draw_circle( x, y, r++, '#' );
  484. draw_circle( x, y, r++, '#' );
  485. }
  486. static void draw_circle( int x, int y, int r, char c )
  487. {
  488. int test, dx, dy;
  489. /* Optimized Bresenham. Kick ass. */
  490. for( test = 0, dx = 0, dy = r ; dx <= dy ; dx++ )
  491. {
  492. gfx_putcharTO( x + dx, y + dy / 2, c );
  493. gfx_putcharTO( x - dx, y + dy / 2, c );
  494. gfx_putcharTO( x + dx, y - dy / 2, c );
  495. gfx_putcharTO( x - dx, y - dy / 2, c );
  496. gfx_putcharTO( x + dy, y + dx / 2, c );
  497. gfx_putcharTO( x - dy, y + dx / 2, c );
  498. gfx_putcharTO( x + dy, y - dx / 2, c );
  499. gfx_putcharTO( x - dy, y - dx / 2, c );
  500. test += test > 0 ? dx - dy-- : dx;
  501. }
  502. }