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.
 
 
 
 
 
 

713 lines
20 KiB

  1. /*
  2. * ttyvaders Textmode shoot'em up
  3. * Copyright (c) 2002 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  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 "common.h"
  24. static void draw_bomb(int x, int y, int vx, int vy);
  25. static void draw_nuke(int x, int y, int frame);
  26. static void draw_beam(int x, int y, int frame);
  27. static void draw_fragbomb(int x, int y, int frame);
  28. void init_weapons(game *g, weapons *wp)
  29. {
  30. int i;
  31. for(i = 0; i < WEAPONS; i++)
  32. {
  33. wp->type[i] = WEAPON_NONE;
  34. }
  35. }
  36. void draw_weapons(game *g, weapons *wp)
  37. {
  38. int i;
  39. for(i = 0; i < WEAPONS; i++)
  40. {
  41. switch(wp->type[i])
  42. {
  43. case WEAPON_LASER:
  44. ee_color(EE_WHITE);
  45. ee_goto(wp->x[i] >> 4, wp->y[i] >> 4);
  46. ee_putchar('|');
  47. ee_color(EE_CYAN);
  48. ee_goto(wp->x[i] >> 4, (wp->y[i] >> 4) + 1);
  49. ee_putchar('|');
  50. break;
  51. case WEAPON_SEEKER:
  52. ee_color(EE_CYAN);
  53. ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4);
  54. ee_putchar('.');
  55. ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4);
  56. ee_putchar('o');
  57. ee_color(EE_WHITE);
  58. ee_goto(wp->x[i] >> 4, wp->y[i] >> 4);
  59. ee_putchar('@');
  60. break;
  61. case WEAPON_BOMB:
  62. ee_color(EE_GRAY);
  63. ee_goto((wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4);
  64. ee_putchar('.');
  65. ee_goto((wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4);
  66. ee_putchar('.');
  67. ee_goto((wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4);
  68. ee_putchar('.');
  69. ee_goto(wp->x3[i] >> 4, wp->y3[i] >> 4);
  70. ee_putchar('.');
  71. ee_goto(wp->x2[i] >> 4, wp->y2[i] >> 4);
  72. ee_putchar('.');
  73. draw_bomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i]);
  74. break;
  75. case WEAPON_FRAGBOMB:
  76. draw_fragbomb(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
  77. break;
  78. case WEAPON_BEAM:
  79. draw_beam(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
  80. break;
  81. case WEAPON_NUKE:
  82. draw_nuke(wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i]);
  83. break;
  84. case WEAPON_LIGHTNING:
  85. case WEAPON_NONE:
  86. break;
  87. }
  88. }
  89. }
  90. void update_weapons(game *g, weapons *wp)
  91. {
  92. int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
  93. for(i = 0; i < WEAPONS; i++)
  94. {
  95. switch(wp->type[i])
  96. {
  97. case WEAPON_LASER:
  98. wp->x[i] += wp->vx[i];
  99. wp->y[i] += wp->vy[i];
  100. if(wp->y[i] < 0)
  101. {
  102. wp->type[i] = WEAPON_NONE;
  103. }
  104. break;
  105. case WEAPON_BOMB:
  106. case WEAPON_SEEKER:
  107. /* Update tail */
  108. wp->x3[i] = wp->x2[i];
  109. wp->y3[i] = wp->y2[i];
  110. wp->x2[i] = wp->x[i];
  111. wp->y2[i] = wp->y[i];
  112. wp->x[i] += wp->vx[i];
  113. wp->y[i] += wp->vy[i];
  114. if(wp->y[i] < 0)
  115. {
  116. wp->type[i] = WEAPON_NONE;
  117. break;
  118. }
  119. if(wp->n[i] < 0)
  120. {
  121. /* Stop updating direction */
  122. break;
  123. }
  124. wp->n[i]--;
  125. /* Estimate our position next frames */
  126. xnew = wp->x[i] + wp->vx[i];
  127. ynew = wp->y[i] + wp->vy[i];
  128. xmin = xnew;
  129. ymin = - (g->h << 4);
  130. dist = (xnew - xmin) * (xnew - xmin)
  131. + 4 * (ynew - ymin) * (ynew - ymin);
  132. /* Find the nearest alien */
  133. for(j = 0; j < ALIENS; j++)
  134. {
  135. if(g->al->type[j] != ALIEN_NONE)
  136. {
  137. int alx = g->al->x[j] << 4;
  138. int aly = g->al->y[j] << 4;
  139. int new = (xnew - alx) * (xnew - alx)
  140. + 4 * (ynew - aly) * (ynew - aly);
  141. if(new <= dist)
  142. {
  143. dist = new;
  144. xmin = alx;
  145. ymin = aly;
  146. }
  147. }
  148. }
  149. /* Find our new direction */
  150. dx = xmin - wp->x[i];
  151. dy = ymin - wp->y[i];
  152. /* Normalize direction */
  153. if(dx | dy)
  154. {
  155. int norm = ee_sqrt(dx * dx + 4 * dy * dy);
  156. dx = dx * 32 / norm;
  157. dy = dy * 32 / norm;
  158. }
  159. /* Find our new speed */
  160. dx = (dx + 3 * wp->vx[i]) / 4;
  161. dy = (dy + 3 * wp->vy[i]) / 4;
  162. /* Normalize speed */
  163. if(dx | dy)
  164. {
  165. int norm = ee_sqrt(dx * dx + 4 * dy * dy);
  166. wp->vx[i] = dx * 32 / norm;
  167. wp->vy[i] = dy * 32 / norm;
  168. }
  169. break;
  170. case WEAPON_FRAGBOMB:
  171. /* If n was set to -1, the fragbomb just exploded */
  172. if(wp->n[i] == -1)
  173. {
  174. int coords[] =
  175. {
  176. 32, 0, -32, 0, 0, 16, 0, -16,
  177. 28, 8, -28, 8, 28, -8, -28, -8,
  178. 24, 12, -24, 12, 24, -12, -24, -12,
  179. 16, 14, -16, 14, 16, -14, -16, -14
  180. };
  181. for(j = 0 ; j < sizeof(coords) / sizeof(int) ; j += 2)
  182. {
  183. add_weapon(g, g->wp, wp->x[i] + coords[j], wp->y[i] + coords[j+1] / 2, coords[j], coords[j+1], WEAPON_SEEKER);
  184. add_weapon(g, g->wp, wp->x[i] + coords[j] / 2, wp->y[i] + coords[j+1], coords[j], coords[j+1], WEAPON_SEEKER);
  185. }
  186. wp->type[i] = WEAPON_NONE;
  187. }
  188. wp->x[i] += wp->vx[i];
  189. wp->y[i] += wp->vy[i];
  190. wp->n[i]++;
  191. if(wp->y[i] < 0)
  192. {
  193. wp->type[i] = WEAPON_NONE;
  194. }
  195. break;
  196. case WEAPON_BEAM:
  197. wp->x[i] = (g->p->x + 2) << 4;
  198. wp->y[i] = g->p->y << 4;
  199. wp->n[i]--;
  200. if(wp->n[i] < 0)
  201. {
  202. wp->type[i] = WEAPON_NONE;
  203. }
  204. break;
  205. case WEAPON_NUKE:
  206. wp->n[i]--;
  207. if(wp->n[i] < 0)
  208. {
  209. wp->type[i] = WEAPON_NONE;
  210. }
  211. break;
  212. case WEAPON_LIGHTNING:
  213. case WEAPON_NONE:
  214. break;
  215. }
  216. }
  217. }
  218. void add_weapon(game *g, weapons *wp, int x, int y, int vx, int vy, int type)
  219. {
  220. int i;
  221. for(i = 0; i < WEAPONS; i++)
  222. {
  223. if(wp->type[i] == WEAPON_NONE)
  224. {
  225. wp->x[i] = x;
  226. wp->y[i] = y;
  227. wp->vx[i] = vx;
  228. wp->vy[i] = vy;
  229. wp->type[i] = type;
  230. wp->n[i] = 0;
  231. switch(type)
  232. {
  233. case WEAPON_LASER:
  234. break;
  235. case WEAPON_FRAGBOMB:
  236. break;
  237. case WEAPON_SEEKER:
  238. case WEAPON_BOMB:
  239. wp->x2[i] = x;
  240. wp->y2[i] = y;
  241. wp->x3[i] = x;
  242. wp->y3[i] = y;
  243. wp->n[i] = 20;
  244. break;
  245. case WEAPON_BEAM:
  246. wp->n[i] = 25;
  247. break;
  248. case WEAPON_NUKE:
  249. wp->n[i] = 25;
  250. break;
  251. case WEAPON_NONE:
  252. break;
  253. }
  254. break;
  255. }
  256. }
  257. }
  258. static void draw_bomb(int x, int y, int vx, int vy)
  259. {
  260. vy *= 2;
  261. ee_color(EE_CYAN);
  262. if(vx > vy)
  263. {
  264. if(vx > -vy) /* right quarter */
  265. {
  266. if(vy > vx/4)
  267. {
  268. /* -1pi/6 */
  269. ee_goto(x-4, y-1);
  270. ee_putstr("/`-.");
  271. ee_goto(x-4, y);
  272. ee_putstr("`-._\\");
  273. ee_color(EE_WHITE);
  274. ee_goto(x-1, y);
  275. ee_putstr("_\\");
  276. ee_goto(x, y+1);
  277. ee_putchar('`');
  278. }
  279. else if(vy < -vx/4)
  280. {
  281. /* 1pi/6 */
  282. ee_goto(x-4, y);
  283. ee_putstr(",-' ");
  284. ee_goto(x-4, y+1);
  285. ee_putstr("\\,-'");
  286. ee_color(EE_WHITE);
  287. ee_goto(x-1, y-1);
  288. ee_putstr("_,");
  289. ee_goto(x, y);
  290. ee_putchar('/');
  291. }
  292. else
  293. {
  294. /* 0pi/6 */
  295. ee_goto(x-4, y-1);
  296. ee_putstr("____");
  297. ee_goto(x-5, y);
  298. ee_putstr("|____");
  299. ee_color(EE_WHITE);
  300. ee_goto(x, y);
  301. ee_putchar('>');
  302. }
  303. }
  304. else /* top quarter */
  305. {
  306. if(vx > -vy/4)
  307. {
  308. /* 2pi/6 */
  309. ee_goto(x-2, y);
  310. ee_putstr("/ ");
  311. ee_goto(x-3, y+1);
  312. ee_putstr("/ /");
  313. ee_goto(x-3, y+2);
  314. ee_putstr("`'");
  315. ee_color(EE_WHITE);
  316. ee_goto(x-1, y-1);
  317. ee_putstr("_,");
  318. ee_goto(x, y);
  319. ee_putchar('|');
  320. }
  321. else if(vx < vy/4)
  322. {
  323. /* 4pi/6 */
  324. ee_goto(x+1, y);
  325. ee_putstr(" \\");
  326. ee_goto(x+1, y+1);
  327. ee_putstr("\\ \\");
  328. ee_goto(x+2, y+2);
  329. ee_putstr("`'");
  330. ee_color(EE_WHITE);
  331. ee_goto(x, y-1);
  332. ee_putstr("._");
  333. ee_goto(x, y);
  334. ee_putchar('|');
  335. }
  336. else
  337. {
  338. /* 3pi/6 */
  339. ee_goto(x-1, y+1);
  340. ee_putstr("| |");
  341. ee_goto(x-1, y+2);
  342. ee_putstr("|_|");
  343. ee_color(EE_WHITE);
  344. ee_goto(x-1, y);
  345. ee_putstr(",^.");
  346. }
  347. }
  348. }
  349. else
  350. {
  351. if(vx > -vy) /* bottom quarter */
  352. {
  353. if(vx > vy/4)
  354. {
  355. /* -2pi/6 */
  356. ee_goto(x-2, y-2);
  357. ee_putstr(",.");
  358. ee_goto(x-2, y-1);
  359. ee_putstr("\\ \\");
  360. ee_goto(x-1, y);
  361. ee_putchar('\\');
  362. ee_color(EE_WHITE);
  363. ee_goto(x, y);
  364. ee_putstr("_|");
  365. }
  366. else if(vx < -vy/4)
  367. {
  368. /* -4pi/6 */
  369. ee_goto(x+1, y-2);
  370. ee_putstr(",.");
  371. ee_goto(x, y-1);
  372. ee_putstr("/ /");
  373. ee_goto(x+1, y);
  374. ee_putchar('/');
  375. ee_color(EE_WHITE);
  376. ee_goto(x-1, y);
  377. ee_putstr("|_/");
  378. }
  379. else
  380. {
  381. /* -3pi/6 */
  382. ee_goto(x, y-3);
  383. ee_putchar('_');
  384. ee_goto(x-1, y-2);
  385. ee_putstr("| |");
  386. ee_goto(x-1, y-1);
  387. ee_putstr("| |");
  388. ee_color(EE_WHITE);
  389. ee_goto(x-1, y);
  390. ee_putstr("`v'");
  391. }
  392. }
  393. else /* left quarter */
  394. {
  395. if(vy > -vx/4)
  396. {
  397. /* -5pi/6 */
  398. ee_goto(x+1, y-1);
  399. ee_putstr(",-'\\");
  400. ee_goto(x+2, y);
  401. ee_putstr(",-'");
  402. ee_goto(x, y+1);
  403. ee_putchar('\'');
  404. ee_color(EE_WHITE);
  405. ee_goto(x, y);
  406. ee_putstr("/_");
  407. }
  408. else if(vy < vx/4)
  409. {
  410. /* 5pi/6 */
  411. ee_goto(x+1, y);
  412. ee_putstr(" `-.");
  413. ee_goto(x+1, y+1);
  414. ee_putstr("`-./");
  415. ee_color(EE_WHITE);
  416. ee_goto(x, y-1);
  417. ee_putstr("._");
  418. ee_goto(x, y);
  419. ee_putchar('\\');
  420. }
  421. else
  422. {
  423. /* 6pi/6 */
  424. ee_goto(x+1, y-1);
  425. ee_putstr("____");
  426. ee_goto(x+1, y);
  427. ee_putstr("____|");
  428. ee_color(EE_WHITE);
  429. ee_goto(x, y);
  430. ee_putchar('<');
  431. }
  432. }
  433. }
  434. }
  435. static void draw_fragbomb(int x, int y, int frame)
  436. {
  437. ee_color(EE_WHITE);
  438. ee_color(frame & 1 ? EE_CYAN : EE_WHITE);
  439. ee_goto(x-2, y);
  440. ee_putstr("( )");
  441. ee_goto(x-1, y+1);
  442. ee_putstr("`--'");
  443. ee_color(frame & 1 ? EE_WHITE : EE_CYAN);
  444. ee_goto(x-1, y-1);
  445. ee_putstr(",--.");
  446. ee_goto(x, y);
  447. ee_putstr("',");
  448. switch(frame % 4)
  449. {
  450. case 0:
  451. ee_color(EE_CYAN);
  452. ee_goto(x, y + 2);
  453. ee_putchar('O');
  454. ee_goto(x + 2, y + 2);
  455. ee_putchar('o');
  456. ee_goto(x + 1, y + 3);
  457. ee_putchar('o');
  458. ee_color(EE_GRAY);
  459. ee_goto(x - 1, y + 3);
  460. ee_putchar(':');
  461. ee_goto(x + 2, y + 4);
  462. ee_putchar(':');
  463. ee_goto(x, y + 4);
  464. ee_putchar('.');
  465. ee_goto(x + 1, y + 5);
  466. ee_putchar('.');
  467. break;
  468. case 1:
  469. ee_color(EE_CYAN);
  470. //ee_goto(x, y + 1);
  471. //ee_putchar('O');
  472. ee_goto(x + 1, y + 2);
  473. ee_putchar('O');
  474. ee_goto(x, y + 3);
  475. ee_putchar('o');
  476. ee_color(EE_GRAY);
  477. ee_goto(x + 2, y + 3);
  478. ee_putchar(':');
  479. ee_goto(x + 1, y + 4);
  480. ee_putchar(':');
  481. ee_goto(x - 1, y + 4);
  482. ee_putchar('.');
  483. ee_goto(x + 2, y + 5);
  484. ee_putchar('.');
  485. break;
  486. case 2:
  487. ee_color(EE_CYAN);
  488. //ee_goto(x - 1, y + 1);
  489. //ee_putchar('O');
  490. ee_goto(x + 2, y + 2);
  491. ee_putchar('O');
  492. ee_goto(x, y + 2);
  493. ee_putchar('o');
  494. ee_goto(x + 1, y + 3);
  495. ee_putchar('o');
  496. ee_color(EE_GRAY);
  497. ee_goto(x, y + 4);
  498. ee_putchar(':');
  499. ee_goto(x + 2, y + 4);
  500. ee_putchar('.');
  501. ee_goto(x + 1, y + 5);
  502. ee_putchar('.');
  503. break;
  504. case 3:
  505. ee_color(EE_CYAN);
  506. //ee_goto(x + 2, y + 1);
  507. //ee_putchar('O');
  508. ee_goto(x + 1, y + 2);
  509. ee_putchar('O');
  510. ee_goto(x - 1, y + 2);
  511. ee_putchar('o');
  512. ee_goto(x + 2, y + 3);
  513. ee_putchar('o');
  514. ee_color(EE_GRAY);
  515. ee_goto(x, y + 3);
  516. ee_putchar(':');
  517. ee_goto(x + 1, y + 4);
  518. ee_putchar(':');
  519. ee_goto(x, y + 5);
  520. ee_putchar('.');
  521. break;
  522. }
  523. }
  524. static void draw_beam(int x, int y, int frame)
  525. {
  526. int r = (29 - frame) * (29 - frame) / 8;
  527. int i;
  528. switch(frame)
  529. {
  530. case 24:
  531. ee_color(EE_WHITE);
  532. ee_goto(x, y-3);
  533. ee_putstr("__");
  534. ee_goto(x-1, y-2);
  535. ee_putchar('\'');
  536. ee_goto(x+2, y-2);
  537. ee_putchar('`');
  538. break;
  539. case 23:
  540. ee_color(EE_CYAN);
  541. ee_goto(x, y-3);
  542. ee_putstr("__");
  543. ee_color(EE_WHITE);
  544. ee_goto(x-2, y-2);
  545. ee_putstr("-'");
  546. ee_goto(x+2, y-2);
  547. ee_putstr("`-");
  548. break;
  549. case 22:
  550. ee_color(EE_CYAN);
  551. ee_goto(x, y-3);
  552. ee_putstr("__");
  553. ee_goto(x-1, y-2);
  554. ee_putchar('\'');
  555. ee_goto(x+2, y-2);
  556. ee_putchar('`');
  557. ee_color(EE_WHITE);
  558. ee_goto(x-3, y-2);
  559. ee_putstr(",-");
  560. ee_goto(x+3, y-2);
  561. ee_putstr("-.");
  562. break;
  563. case 21:
  564. ee_color(EE_CYAN);
  565. ee_goto(x-1, y-3);
  566. ee_putstr("____");
  567. ee_goto(x-2, y-2);
  568. ee_putchar('\'');
  569. ee_goto(x+3, y-2);
  570. ee_putchar('`');
  571. ee_color(EE_WHITE);
  572. ee_goto(x-4, y-2);
  573. ee_putstr(",-");
  574. ee_goto(x+4, y-2);
  575. ee_putstr("-.");
  576. break;
  577. case 20:
  578. ee_color(EE_WHITE);
  579. ee_goto(x, y-3);
  580. ee_putstr("%%");
  581. ee_goto(x-4, y-2);
  582. ee_putchar(',');
  583. ee_goto(x+5, y-2);
  584. ee_putchar('.');
  585. ee_color(EE_CYAN);
  586. ee_goto(x-1, y-3);
  587. ee_putchar(':');
  588. ee_goto(x+2, y-3);
  589. ee_putchar(':');
  590. ee_goto(x-3, y-2);
  591. ee_putstr("-'");
  592. ee_goto(x+3, y-2);
  593. ee_putstr("`-");
  594. break;
  595. case 19:
  596. ee_color(EE_WHITE);
  597. ee_goto(x, y-4);
  598. ee_putstr("%%");
  599. ee_goto(x, y-3);
  600. ee_putstr("##");
  601. ee_color(EE_CYAN);
  602. ee_goto(x-1, y-4);
  603. ee_putchar(':');
  604. ee_goto(x+2, y-4);
  605. ee_putchar(':');
  606. ee_goto(x-1, y-3);
  607. ee_putchar('%');
  608. ee_goto(x+2, y-3);
  609. ee_putchar('%');
  610. ee_goto(x-4, y-2);
  611. ee_putstr(",-'");
  612. ee_goto(x+3, y-2);
  613. ee_putstr("`-.");
  614. ee_color(EE_BLUE);
  615. ee_goto(x-2, y-3);
  616. ee_putchar(':');
  617. ee_goto(x+3, y-3);
  618. ee_putchar(':');
  619. break;
  620. case 18:
  621. default:
  622. r = (18 - frame) * (18 - frame);
  623. ee_color(EE_WHITE);
  624. ee_goto(x-1, y-5-r);
  625. ee_putstr(":%%:");
  626. ee_goto(x-1, y-4-r);
  627. ee_putstr("%##%");
  628. ee_color(EE_CYAN);
  629. ee_goto(x-2, y-4-r);
  630. ee_putchar(':');
  631. ee_goto(x+3, y-4-r);
  632. ee_putchar(':');
  633. ee_goto(x-2, y-2);
  634. ee_putchar('\'');
  635. ee_goto(x+3, y-2);
  636. ee_putchar('`');
  637. ee_color(EE_BLUE);
  638. ee_goto(x-3, y-2);
  639. ee_putchar(':');
  640. ee_goto(x+4, y-2);
  641. ee_putchar(':');
  642. for(i = 0; i <= r; i++)
  643. {
  644. ee_color(EE_WHITE);
  645. ee_goto(x-1, y-3-i);
  646. ee_putstr((i+frame) % 5 ? "####" : "%%%%");
  647. ee_color(EE_CYAN);
  648. ee_goto(x-2, y-3-i);
  649. ee_putchar('%');
  650. ee_goto(x+3, y-3-i);
  651. ee_putchar('%');
  652. ee_color(EE_BLUE);
  653. ee_goto(x-3, y-3-i);
  654. ee_putchar(':');
  655. ee_goto(x+4, y-3-i);
  656. ee_putchar(':');
  657. }
  658. break;
  659. }
  660. }
  661. static void draw_nuke(int x, int y, int frame)
  662. {
  663. int r = (29 - frame) * (29 - frame) / 8;
  664. /* Lots of duplicate pixels, but we don't care */
  665. ee_color(EE_BLUE);
  666. ee_draw_circle(x, y, r++, ':');
  667. ee_color(EE_CYAN);
  668. ee_draw_circle(x, y, r++, '%');
  669. ee_color(EE_WHITE);
  670. ee_draw_circle(x, y, r++, '#');
  671. ee_draw_circle(x, y, r++, '#');
  672. }