589 lignes
17 KiB

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