Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

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