source: ttyvaders/trunk/src/weapons.c @ 88

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