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

Last change on this file since 36 was 36, checked in by Sam Hocevar, 18 years ago
  • added the COPYING file (GPLv2).
  • added GPL headers to source files.
File size: 17.3 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: 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
23#include <stdlib.h>
24#include <math.h>
25
26#include "common.h"
27
28static void draw_bomb( int x, int y, int vx, int vy );
29static void draw_nuke( int x, int y, int frame );
30static void draw_beam( int x, int y, int frame );
31static void draw_circle( int x, int y, int r, char c );
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                gfx_color( WHITE );
53                gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
54                gfx_putchar( '|' );
55                gfx_color( CYAN );
56                gfx_goto( wp->x[i] >> 4, (wp->y[i] >> 4) + 1 );
57                gfx_putchar( '|' );
58                break;
59            case WEAPON_SEEKER:
60                gfx_color( CYAN );
61                gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
62                gfx_putchar( '.' );
63                gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
64                gfx_putchar( 'o' );
65                gfx_color( WHITE );
66                gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
67                gfx_putchar( '@' );
68                break;
69            case WEAPON_BOMB:
70                gfx_color( GRAY );
71                gfx_goto( (wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4 );
72                gfx_putchar( '.' );
73                gfx_goto( (wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4 );
74                gfx_putchar( '.' );
75                gfx_goto( (wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4 );
76                gfx_putchar( '.' );
77                gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
78                gfx_putchar( '.' );
79                gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
80                gfx_putchar( '.' );
81                draw_bomb( wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[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_NONE:
90                break;
91        }
92    }
93}
94
95void update_weapons( game *g, weapons *wp )
96{
97    int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
98
99    for( i = 0; i < WEAPONS; i++ )
100    {
101        switch( wp->type[i] )
102        {
103            case WEAPON_LASER:
104                wp->x[i] += wp->vx[i];
105                wp->y[i] += wp->vy[i];
106                if( wp->y[i] < 0 )
107                {
108                    wp->type[i] = WEAPON_NONE;
109                }
110                break;
111            case WEAPON_BOMB:
112            case WEAPON_SEEKER:
113                /* Update tail */
114                wp->x3[i] = wp->x2[i];
115                wp->y3[i] = wp->y2[i];
116
117                wp->x2[i] = wp->x[i];
118                wp->y2[i] = wp->y[i];
119
120                wp->x[i] += wp->vx[i];
121                wp->y[i] += wp->vy[i];
122
123                if( wp->y[i] < 0 )
124                {
125                    wp->type[i] = WEAPON_NONE;
126                    break;
127                }
128
129                if( wp->n[i] < 0 )
130                {
131                    /* Stop updating direction */
132                    break;
133                }
134
135                wp->n[i]--;
136
137                /* Estimate our position in 2 frames */
138                xnew = wp->x[i] + 4 * wp->vx[i];
139                ynew = wp->y[i] + 4 * wp->vy[i];
140
141                xmin = xnew;
142                ymin = - (g->h << 4);
143                dist = (xnew - xmin) * (xnew - xmin)
144                        + 4 * (ynew - ymin) * (ynew - ymin);
145
146                /* Find the nearest alien */
147                for( j = 0; j < ALIENS; j++ )
148                {
149                    if( g->al->type[j] != ALIEN_NONE )
150                    {
151                        int alx = g->al->x[j] << 4;
152                        int aly = g->al->y[j] << 4;
153                        int new = (xnew - alx) * (xnew - alx)
154                                   + 4 * (ynew - aly) * (ynew - aly);
155                        if( new <= dist )
156                        {
157                            dist = new;
158                            xmin = alx;
159                            ymin = aly;
160                        }
161                    }
162                }
163
164                /* Find our new direction */
165                dx = xmin - wp->x[i];
166                dy = ymin - wp->y[i];
167
168                /* Normalize and update speed */
169                wp->vx[i] = (7 * wp->vx[i]
170                              + (dx * 48) / sqrt(dx*dx+dy*dy) ) / 8;
171                wp->vy[i] = (7 * wp->vy[i]
172                              + (dy * 24) / sqrt(dx*dx+dy*dy) ) / 8;
173
174                break;
175            case WEAPON_BEAM:
176                wp->x[i] = (g->p->x + 2) << 4;
177                wp->y[i] = g->p->y << 4;
178                wp->n[i]--;
179                if( wp->n[i] < 0 )
180                {
181                    wp->type[i] = WEAPON_NONE;
182                }
183                break;
184            case WEAPON_NUKE:
185                wp->n[i]--;
186                if( wp->n[i] < 0 )
187                {
188                    wp->type[i] = WEAPON_NONE;
189                }
190                break;
191            case WEAPON_NONE:
192                break;
193        }
194    }
195}
196
197void add_weapon( game *g, weapons *wp, int x, int y, int vx, int vy, int type )
198{
199    int i;
200
201    for( i = 0; i < WEAPONS; i++ )
202    {
203        if( wp->type[i] == WEAPON_NONE )
204        {
205            wp->x[i] = x;
206            wp->y[i] = y;
207            wp->vx[i] = vx;
208            wp->vy[i] = vy;
209            wp->type[i] = type;
210            switch( type )
211            {
212                case WEAPON_LASER:
213                    break;
214                case WEAPON_SEEKER:
215                case WEAPON_BOMB:
216                    wp->x2[i] = x;
217                    wp->y2[i] = y;
218                    wp->x3[i] = x;
219                    wp->y3[i] = y;
220                    wp->n[i] = 20;
221                    break;
222                case WEAPON_BEAM:
223                    wp->n[i] = 25;
224                    break;
225                case WEAPON_NUKE:
226                    wp->n[i] = 25;
227                    break;
228                case WEAPON_NONE:
229                    break;
230            }
231            break;
232        }
233    }
234}
235
236static void draw_bomb( int x, int y, int vx, int vy )
237{
238    vy *= 2;
239    gfx_color( CYAN );
240
241    if( vx > vy )
242    {
243        if( vx > -vy ) /* right quarter */
244        {
245            if( vy > vx/4 )
246            {
247                /* -1pi/6 */
248                gfx_goto( x-4, y-1 );
249                gfx_putstr( "/`-." );
250                gfx_goto( x-4, y );
251                gfx_putstr( "`-._\\" );
252                gfx_color( WHITE );
253                gfx_goto( x-1, y );
254                gfx_putstr( "_\\" );
255                gfx_goto( x, y+1 );
256                gfx_putchar( '`' );
257            }
258            else if( vy < -vx/4 )
259            {
260                /* 1pi/6 */
261                gfx_goto( x-4, y );
262                gfx_putstr( ",-' " );
263                gfx_goto( x-4, y+1 );
264                gfx_putstr( "\\,-'" );
265                gfx_color( WHITE );
266                gfx_goto( x-1, y-1 );
267                gfx_putstr( "_," );
268                gfx_goto( x, y );
269                gfx_putchar( '/' );
270            }
271            else
272            {
273                /* 0pi/6 */
274                gfx_goto( x-4, y-1 );
275                gfx_putstr( "____" );
276                gfx_goto( x-5, y );
277                gfx_putstr( "|____" );
278                gfx_color( WHITE );
279                gfx_goto( x, y );
280                gfx_putchar( '>' );
281            }
282        }
283        else /* top quarter */
284        {
285            if( vx > -vy/4 )
286            {
287                /* 2pi/6 */
288                gfx_goto( x-2, y );
289                gfx_putstr( "/ " );
290                gfx_goto( x-3, y+1 );
291                gfx_putstr( "/ /" );
292                gfx_goto( x-3, y+2 );
293                gfx_putstr( "`'" );
294                gfx_color( WHITE );
295                gfx_goto( x-1, y-1 );
296                gfx_putstr( "_," );
297                gfx_goto( x, y );
298                gfx_putchar( '|' );
299            }
300            else if( vx < vy/4 )
301            {
302                /* 4pi/6 */
303                gfx_goto( x+1, y );
304                gfx_putstr( " \\" );
305                gfx_goto( x+1, y+1 );
306                gfx_putstr( "\\ \\" );
307                gfx_goto( x+2, y+2 );
308                gfx_putstr( "`'" );
309                gfx_color( WHITE );
310                gfx_goto( x, y-1 );
311                gfx_putstr( "._" );
312                gfx_goto( x, y );
313                gfx_putchar( '|' );
314            }
315            else
316            {
317                /* 3pi/6 */
318                gfx_goto( x-1, y+1 );
319                gfx_putstr( "| |" );
320                gfx_goto( x-1, y+2 );
321                gfx_putstr( "|_|" );
322                gfx_color( WHITE );
323                gfx_goto( x-1, y );
324                gfx_putstr( ",^." );
325            }
326        }
327    }
328    else
329    {
330        if( vx > -vy ) /* bottom quarter */
331        {
332            if( vx > vy/4 )
333            {
334                /* -2pi/6 */
335                gfx_goto( x-2, y-2 );
336                gfx_putstr( ",." );
337                gfx_goto( x-2, y-1 );
338                gfx_putstr( "\\ \\" );
339                gfx_goto( x-1, y );
340                gfx_putchar( '\\' );
341                gfx_color( WHITE );
342                gfx_goto( x, y );
343                gfx_putstr( "_|" );
344            }
345            else if( vx < -vy/4 )
346            {
347                /* -4pi/6 */
348                gfx_goto( x+1, y-2 );
349                gfx_putstr( ",." );
350                gfx_goto( x, y-1 );
351                gfx_putstr( "/ /" );
352                gfx_goto( x+1, y );
353                gfx_putchar( '/' );
354                gfx_color( WHITE );
355                gfx_goto( x-1, y );
356                gfx_putstr( "|_/" );
357            }
358            else
359            {
360                /* -3pi/6 */
361                gfx_goto( x, y-3 );
362                gfx_putchar( '_' );
363                gfx_goto( x-1, y-2 );
364                gfx_putstr( "| |" );
365                gfx_goto( x-1, y-1 );
366                gfx_putstr( "| |" );
367                gfx_color( WHITE );
368                gfx_goto( x-1, y );
369                gfx_putstr( "`v'" );
370            }
371        }
372        else /* left quarter */
373        {
374            if( vy > -vx/4 )
375            {
376                /* -5pi/6 */
377                gfx_goto( x+1, y-1 );
378                gfx_putstr( ",-'\\" );
379                gfx_goto( x+2, y );
380                gfx_putstr( ",-'" );
381                gfx_goto( x, y+1 );
382                gfx_putchar( '\'' );
383                gfx_color( WHITE );
384                gfx_goto( x, y );
385                gfx_putstr( "/_" );
386            }
387            else if( vy < vx/4 )
388            {
389                /* 5pi/6 */
390                gfx_goto( x+1, y );
391                gfx_putstr( " `-." );
392                gfx_goto( x+1, y+1 );
393                gfx_putstr( "`-./" );
394                gfx_color( WHITE );
395                gfx_goto( x, y-1 );
396                gfx_putstr( "._" );
397                gfx_goto( x, y );
398                gfx_putchar( '\\' );
399            }
400            else
401            {
402                /* 6pi/6 */
403                gfx_goto( x+1, y-1 );
404                gfx_putstr( "____" );
405                gfx_goto( x+1, y );
406                gfx_putstr( "____|" );
407                gfx_color( WHITE );
408                gfx_goto( x, y );
409                gfx_putchar( '<' );
410            }
411        }
412    }
413}
414
415static void draw_beam( int x, int y, int frame )
416{
417    int r = (29 - frame) * (29 - frame) / 8;
418    int i;
419
420    switch( frame )
421    {
422        case 24:
423            gfx_color( WHITE );
424            gfx_goto( x, y-3 );
425            gfx_putstr( "__" );
426            gfx_goto( x-1, y-2 );
427            gfx_putchar( '\'' );
428            gfx_goto( x+2, y-2 );
429            gfx_putchar( '`' );
430            break;
431        case 23:
432            gfx_color( CYAN );
433            gfx_goto( x, y-3 );
434            gfx_putstr( "__" );
435            gfx_color( WHITE );
436            gfx_goto( x-2, y-2 );
437            gfx_putstr( "-'" );
438            gfx_goto( x+2, y-2 );
439            gfx_putstr( "`-" );
440            break;
441        case 22:
442            gfx_color( CYAN );
443            gfx_goto( x, y-3 );
444            gfx_putstr( "__" );
445            gfx_goto( x-1, y-2 );
446            gfx_putchar( '\'' );
447            gfx_goto( x+2, y-2 );
448            gfx_putchar( '`' );
449            gfx_color( WHITE );
450            gfx_goto( x-3, y-2 );
451            gfx_putstr( ",-" );
452            gfx_goto( x+3, y-2 );
453            gfx_putstr( "-." );
454            break;
455        case 21:
456            gfx_color( CYAN );
457            gfx_goto( x-1, y-3 );
458            gfx_putstr( "____" );
459            gfx_goto( x-2, y-2 );
460            gfx_putchar( '\'' );
461            gfx_goto( x+3, y-2 );
462            gfx_putchar( '`' );
463            gfx_color( WHITE );
464            gfx_goto( x-4, y-2 );
465            gfx_putstr( ",-" );
466            gfx_goto( x+4, y-2 );
467            gfx_putstr( "-." );
468            break;
469        case 20:
470            gfx_color( WHITE );
471            gfx_goto( x, y-3 );
472            gfx_putstr( "%%" );
473            gfx_goto( x-4, y-2 );
474            gfx_putchar( ',' );
475            gfx_goto( x+5, y-2 );
476            gfx_putchar( '.' );
477            gfx_color( CYAN );
478            gfx_goto( x-1, y-3 );
479            gfx_putchar( ':' );
480            gfx_goto( x+2, y-3 );
481            gfx_putchar( ':' );
482            gfx_goto( x-3, y-2 );
483            gfx_putstr( "-'" );
484            gfx_goto( x+3, y-2 );
485            gfx_putstr( "`-" );
486            break;
487        case 19:
488            gfx_color( WHITE );
489            gfx_goto( x, y-4 );
490            gfx_putstr( "%%" );
491            gfx_goto( x, y-3 );
492            gfx_putstr( "##" );
493            gfx_color( CYAN );
494            gfx_goto( x-1, y-4 );
495            gfx_putchar( ':' );
496            gfx_goto( x+2, y-4 );
497            gfx_putchar( ':' );
498            gfx_goto( x-1, y-3 );
499            gfx_putchar( '%' );
500            gfx_goto( x+2, y-3 );
501            gfx_putchar( '%' );
502            gfx_goto( x-4, y-2 );
503            gfx_putstr( ",-'" );
504            gfx_goto( x+3, y-2 );
505            gfx_putstr( "`-." );
506            gfx_color( BLUE );
507            gfx_goto( x-2, y-3 );
508            gfx_putchar( ':' );
509            gfx_goto( x+3, y-3 );
510            gfx_putchar( ':' );
511            break;
512        case 18:
513        default:
514            r = (18 - frame) * (18 - frame);
515            gfx_color( WHITE );
516            gfx_goto( x-1, y-5-r );
517            gfx_putstr( ":%%:" );
518            gfx_goto( x-1, y-4-r );
519            gfx_putstr( "%##%" );
520            gfx_color( CYAN );
521            gfx_goto( x-2, y-4-r );
522            gfx_putchar( ':' );
523            gfx_goto( x+3, y-4-r );
524            gfx_putchar( ':' );
525            gfx_goto( x-2, y-2 );
526            gfx_putchar( '\'' );
527            gfx_goto( x+3, y-2 );
528            gfx_putchar( '`' );
529            gfx_color( BLUE );
530            gfx_goto( x-3, y-2 );
531            gfx_putchar( ':' );
532            gfx_goto( x+4, y-2 );
533            gfx_putchar( ':' );
534            for( i = 0; i <= r; i++ )
535            {
536                gfx_color( WHITE );
537                gfx_goto( x-1, y-3-i );
538                gfx_putstr( (i+frame) % 5 ? "####" : "%%%%" );
539                gfx_color( CYAN );
540                gfx_goto( x-2, y-3-i );
541                gfx_putchar( '%' );
542                gfx_goto( x+3, y-3-i );
543                gfx_putchar( '%' );
544                gfx_color( BLUE );
545                gfx_goto( x-3, y-3-i );
546                gfx_putchar( ':' );
547                gfx_goto( x+4, y-3-i );
548                gfx_putchar( ':' );
549            }
550            break;
551    }
552}
553
554static void draw_nuke( int x, int y, int frame )
555{
556    int r = (29 - frame) * (29 - frame) / 8;
557
558    /* Lots of duplicate pixels, but we don't care */
559    gfx_color( BLUE );
560    draw_circle( x, y, r++, ':' );
561    gfx_color( CYAN );
562    draw_circle( x, y, r++, '%' );
563    gfx_color( WHITE );
564    draw_circle( x, y, r++, '#' );
565    draw_circle( x, y, r++, '#' );
566}
567
568static void draw_circle( int x, int y, int r, char c )
569{
570    int test, dx, dy;
571
572    /* Optimized Bresenham. Kick ass. */
573    for( test = 0, dx = 0, dy = r ; dx <= dy ; dx++ )
574    {
575        gfx_putcharTO( x + dx, y + dy / 2, c );
576        gfx_putcharTO( x - dx, y + dy / 2, c );
577        gfx_putcharTO( x + dx, y - dy / 2, c );
578        gfx_putcharTO( x - dx, y - dy / 2, c );
579
580        gfx_putcharTO( x + dy, y + dx / 2, c );
581        gfx_putcharTO( x - dy, y + dx / 2, c );
582        gfx_putcharTO( x + dy, y - dx / 2, c );
583        gfx_putcharTO( x - dy, y - dx / 2, c );
584
585        test += test > 0 ? dx - dy-- : dx;
586    }
587}
588
Note: See TracBrowser for help on using the repository browser.