|
- /*
- * ttyvaders Textmode shoot'em up
- * Copyright (c) 2002 Sam Hocevar <sam@zoy.org>
- * All Rights Reserved
- *
- * $Id: tarass
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <stdlib.h>
- #include <math.h>
-
- #include "common.h"
-
- static void draw_bomb( int x, int y, int vx, int vy );
- static void draw_nuke( int x, int y, int frame );
- static void draw_beam( int x, int y, int frame );
- static void draw_circle( int x, int y, int r, char c );
-
- void init_weapons( game *g, weapons *wp )
- {
- int i;
-
- for( i = 0; i < WEAPONS; i++ )
- {
- wp->type[i] = WEAPON_NONE;
- }
- }
-
- void draw_weapons( game *g, weapons *wp )
- {
- int i;
-
- for( i = 0; i < WEAPONS; i++ )
- {
- switch( wp->type[i] )
- {
- case WEAPON_LASER:
- gfx_color( WHITE );
- gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
- gfx_putchar( '|' );
- gfx_color( CYAN );
- gfx_goto( wp->x[i] >> 4, (wp->y[i] >> 4) + 1 );
- gfx_putchar( '|' );
- break;
- case WEAPON_SEEKER:
- gfx_color( CYAN );
- gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
- gfx_putchar( '.' );
- gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
- gfx_putchar( 'o' );
- gfx_color( WHITE );
- gfx_goto( wp->x[i] >> 4, wp->y[i] >> 4 );
- gfx_putchar( '@' );
- break;
- case WEAPON_BOMB:
- gfx_color( GRAY );
- gfx_goto( (wp->x[i] - wp->vx[i]) >> 4, (wp->y[i] - wp->vy[i]) >> 4 );
- gfx_putchar( '.' );
- gfx_goto( (wp->x3[i] - wp->vx[i]) >> 4, (wp->y3[i] - wp->vy[i]) >> 4 );
- gfx_putchar( '.' );
- gfx_goto( (wp->x2[i] - wp->vx[i]) >> 4, (wp->y2[i] - wp->vy[i]) >> 4 );
- gfx_putchar( '.' );
- gfx_goto( wp->x3[i] >> 4, wp->y3[i] >> 4 );
- gfx_putchar( '.' );
- gfx_goto( wp->x2[i] >> 4, wp->y2[i] >> 4 );
- gfx_putchar( '.' );
- draw_bomb( wp->x[i] >> 4, wp->y[i] >> 4, wp->vx[i], wp->vy[i] );
- break;
- case WEAPON_BEAM:
- draw_beam( wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i] );
- break;
- case WEAPON_NUKE:
- draw_nuke( wp->x[i] >> 4, wp->y[i] >> 4, wp->n[i] );
- break;
- case WEAPON_NONE:
- break;
- }
- }
- }
-
- void update_weapons( game *g, weapons *wp )
- {
- int i, j, dist, xmin, ymin, dx, dy, xnew, ynew;
-
- for( i = 0; i < WEAPONS; i++ )
- {
- switch( wp->type[i] )
- {
- case WEAPON_LASER:
- wp->x[i] += wp->vx[i];
- wp->y[i] += wp->vy[i];
- if( wp->y[i] < 0 )
- {
- wp->type[i] = WEAPON_NONE;
- }
- break;
- case WEAPON_BOMB:
- case WEAPON_SEEKER:
- /* Update tail */
- wp->x3[i] = wp->x2[i];
- wp->y3[i] = wp->y2[i];
-
- wp->x2[i] = wp->x[i];
- wp->y2[i] = wp->y[i];
-
- wp->x[i] += wp->vx[i];
- wp->y[i] += wp->vy[i];
-
- if( wp->y[i] < 0 )
- {
- wp->type[i] = WEAPON_NONE;
- break;
- }
-
- if( wp->n[i] < 0 )
- {
- /* Stop updating direction */
- break;
- }
-
- wp->n[i]--;
-
- /* Estimate our position in 2 frames */
- xnew = wp->x[i] + 4 * wp->vx[i];
- ynew = wp->y[i] + 4 * wp->vy[i];
-
- xmin = xnew;
- ymin = - (g->h << 4);
- dist = (xnew - xmin) * (xnew - xmin)
- + 4 * (ynew - ymin) * (ynew - ymin);
-
- /* Find the nearest alien */
- for( j = 0; j < ALIENS; j++ )
- {
- if( g->al->type[j] != ALIEN_NONE )
- {
- int alx = g->al->x[j] << 4;
- int aly = g->al->y[j] << 4;
- int new = (xnew - alx) * (xnew - alx)
- + 4 * (ynew - aly) * (ynew - aly);
- if( new <= dist )
- {
- dist = new;
- xmin = alx;
- ymin = aly;
- }
- }
- }
-
- /* Find our new direction */
- dx = xmin - wp->x[i];
- dy = ymin - wp->y[i];
-
- /* Normalize and update speed */
- wp->vx[i] = (7 * wp->vx[i]
- + (dx * 48) / sqrt(dx*dx+dy*dy) ) / 8;
- wp->vy[i] = (7 * wp->vy[i]
- + (dy * 24) / sqrt(dx*dx+dy*dy) ) / 8;
-
- break;
- case WEAPON_BEAM:
- wp->x[i] = (g->p->x + 2) << 4;
- wp->y[i] = g->p->y << 4;
- wp->n[i]--;
- if( wp->n[i] < 0 )
- {
- wp->type[i] = WEAPON_NONE;
- }
- break;
- case WEAPON_NUKE:
- wp->n[i]--;
- if( wp->n[i] < 0 )
- {
- wp->type[i] = WEAPON_NONE;
- }
- break;
- case WEAPON_NONE:
- break;
- }
- }
- }
-
- void add_weapon( game *g, weapons *wp, int x, int y, int vx, int vy, int type )
- {
- int i;
-
- for( i = 0; i < WEAPONS; i++ )
- {
- if( wp->type[i] == WEAPON_NONE )
- {
- wp->x[i] = x;
- wp->y[i] = y;
- wp->vx[i] = vx;
- wp->vy[i] = vy;
- wp->type[i] = type;
- switch( type )
- {
- case WEAPON_LASER:
- break;
- case WEAPON_SEEKER:
- case WEAPON_BOMB:
- wp->x2[i] = x;
- wp->y2[i] = y;
- wp->x3[i] = x;
- wp->y3[i] = y;
- wp->n[i] = 20;
- break;
- case WEAPON_BEAM:
- wp->n[i] = 25;
- break;
- case WEAPON_NUKE:
- wp->n[i] = 25;
- break;
- case WEAPON_NONE:
- break;
- }
- break;
- }
- }
- }
-
- static void draw_bomb( int x, int y, int vx, int vy )
- {
- vy *= 2;
- gfx_color( CYAN );
-
- if( vx > vy )
- {
- if( vx > -vy ) /* right quarter */
- {
- if( vy > vx/4 )
- {
- /* -1pi/6 */
- gfx_goto( x-4, y-1 );
- gfx_putstr( "/`-." );
- gfx_goto( x-4, y );
- gfx_putstr( "`-._\\" );
- gfx_color( WHITE );
- gfx_goto( x-1, y );
- gfx_putstr( "_\\" );
- gfx_goto( x, y+1 );
- gfx_putchar( '`' );
- }
- else if( vy < -vx/4 )
- {
- /* 1pi/6 */
- gfx_goto( x-4, y );
- gfx_putstr( ",-' " );
- gfx_goto( x-4, y+1 );
- gfx_putstr( "\\,-'" );
- gfx_color( WHITE );
- gfx_goto( x-1, y-1 );
- gfx_putstr( "_," );
- gfx_goto( x, y );
- gfx_putchar( '/' );
- }
- else
- {
- /* 0pi/6 */
- gfx_goto( x-4, y-1 );
- gfx_putstr( "____" );
- gfx_goto( x-5, y );
- gfx_putstr( "|____" );
- gfx_color( WHITE );
- gfx_goto( x, y );
- gfx_putchar( '>' );
- }
- }
- else /* top quarter */
- {
- if( vx > -vy/4 )
- {
- /* 2pi/6 */
- gfx_goto( x-2, y );
- gfx_putstr( "/ " );
- gfx_goto( x-3, y+1 );
- gfx_putstr( "/ /" );
- gfx_goto( x-3, y+2 );
- gfx_putstr( "`'" );
- gfx_color( WHITE );
- gfx_goto( x-1, y-1 );
- gfx_putstr( "_," );
- gfx_goto( x, y );
- gfx_putchar( '|' );
- }
- else if( vx < vy/4 )
- {
- /* 4pi/6 */
- gfx_goto( x+1, y );
- gfx_putstr( " \\" );
- gfx_goto( x+1, y+1 );
- gfx_putstr( "\\ \\" );
- gfx_goto( x+2, y+2 );
- gfx_putstr( "`'" );
- gfx_color( WHITE );
- gfx_goto( x, y-1 );
- gfx_putstr( "._" );
- gfx_goto( x, y );
- gfx_putchar( '|' );
- }
- else
- {
- /* 3pi/6 */
- gfx_goto( x-1, y+1 );
- gfx_putstr( "| |" );
- gfx_goto( x-1, y+2 );
- gfx_putstr( "|_|" );
- gfx_color( WHITE );
- gfx_goto( x-1, y );
- gfx_putstr( ",^." );
- }
- }
- }
- else
- {
- if( vx > -vy ) /* bottom quarter */
- {
- if( vx > vy/4 )
- {
- /* -2pi/6 */
- gfx_goto( x-2, y-2 );
- gfx_putstr( ",." );
- gfx_goto( x-2, y-1 );
- gfx_putstr( "\\ \\" );
- gfx_goto( x-1, y );
- gfx_putchar( '\\' );
- gfx_color( WHITE );
- gfx_goto( x, y );
- gfx_putstr( "_|" );
- }
- else if( vx < -vy/4 )
- {
- /* -4pi/6 */
- gfx_goto( x+1, y-2 );
- gfx_putstr( ",." );
- gfx_goto( x, y-1 );
- gfx_putstr( "/ /" );
- gfx_goto( x+1, y );
- gfx_putchar( '/' );
- gfx_color( WHITE );
- gfx_goto( x-1, y );
- gfx_putstr( "|_/" );
- }
- else
- {
- /* -3pi/6 */
- gfx_goto( x, y-3 );
- gfx_putchar( '_' );
- gfx_goto( x-1, y-2 );
- gfx_putstr( "| |" );
- gfx_goto( x-1, y-1 );
- gfx_putstr( "| |" );
- gfx_color( WHITE );
- gfx_goto( x-1, y );
- gfx_putstr( "`v'" );
- }
- }
- else /* left quarter */
- {
- if( vy > -vx/4 )
- {
- /* -5pi/6 */
- gfx_goto( x+1, y-1 );
- gfx_putstr( ",-'\\" );
- gfx_goto( x+2, y );
- gfx_putstr( ",-'" );
- gfx_goto( x, y+1 );
- gfx_putchar( '\'' );
- gfx_color( WHITE );
- gfx_goto( x, y );
- gfx_putstr( "/_" );
- }
- else if( vy < vx/4 )
- {
- /* 5pi/6 */
- gfx_goto( x+1, y );
- gfx_putstr( " `-." );
- gfx_goto( x+1, y+1 );
- gfx_putstr( "`-./" );
- gfx_color( WHITE );
- gfx_goto( x, y-1 );
- gfx_putstr( "._" );
- gfx_goto( x, y );
- gfx_putchar( '\\' );
- }
- else
- {
- /* 6pi/6 */
- gfx_goto( x+1, y-1 );
- gfx_putstr( "____" );
- gfx_goto( x+1, y );
- gfx_putstr( "____|" );
- gfx_color( WHITE );
- gfx_goto( x, y );
- gfx_putchar( '<' );
- }
- }
- }
- }
-
- static void draw_beam( int x, int y, int frame )
- {
- int r = (29 - frame) * (29 - frame) / 8;
- int i;
-
- switch( frame )
- {
- case 24:
- gfx_color( WHITE );
- gfx_goto( x, y-3 );
- gfx_putstr( "__" );
- gfx_goto( x-1, y-2 );
- gfx_putchar( '\'' );
- gfx_goto( x+2, y-2 );
- gfx_putchar( '`' );
- break;
- case 23:
- gfx_color( CYAN );
- gfx_goto( x, y-3 );
- gfx_putstr( "__" );
- gfx_color( WHITE );
- gfx_goto( x-2, y-2 );
- gfx_putstr( "-'" );
- gfx_goto( x+2, y-2 );
- gfx_putstr( "`-" );
- break;
- case 22:
- gfx_color( CYAN );
- gfx_goto( x, y-3 );
- gfx_putstr( "__" );
- gfx_goto( x-1, y-2 );
- gfx_putchar( '\'' );
- gfx_goto( x+2, y-2 );
- gfx_putchar( '`' );
- gfx_color( WHITE );
- gfx_goto( x-3, y-2 );
- gfx_putstr( ",-" );
- gfx_goto( x+3, y-2 );
- gfx_putstr( "-." );
- break;
- case 21:
- gfx_color( CYAN );
- gfx_goto( x-1, y-3 );
- gfx_putstr( "____" );
- gfx_goto( x-2, y-2 );
- gfx_putchar( '\'' );
- gfx_goto( x+3, y-2 );
- gfx_putchar( '`' );
- gfx_color( WHITE );
- gfx_goto( x-4, y-2 );
- gfx_putstr( ",-" );
- gfx_goto( x+4, y-2 );
- gfx_putstr( "-." );
- break;
- case 20:
- gfx_color( WHITE );
- gfx_goto( x, y-3 );
- gfx_putstr( "%%" );
- gfx_goto( x-4, y-2 );
- gfx_putchar( ',' );
- gfx_goto( x+5, y-2 );
- gfx_putchar( '.' );
- gfx_color( CYAN );
- gfx_goto( x-1, y-3 );
- gfx_putchar( ':' );
- gfx_goto( x+2, y-3 );
- gfx_putchar( ':' );
- gfx_goto( x-3, y-2 );
- gfx_putstr( "-'" );
- gfx_goto( x+3, y-2 );
- gfx_putstr( "`-" );
- break;
- case 19:
- gfx_color( WHITE );
- gfx_goto( x, y-4 );
- gfx_putstr( "%%" );
- gfx_goto( x, y-3 );
- gfx_putstr( "##" );
- gfx_color( CYAN );
- gfx_goto( x-1, y-4 );
- gfx_putchar( ':' );
- gfx_goto( x+2, y-4 );
- gfx_putchar( ':' );
- gfx_goto( x-1, y-3 );
- gfx_putchar( '%' );
- gfx_goto( x+2, y-3 );
- gfx_putchar( '%' );
- gfx_goto( x-4, y-2 );
- gfx_putstr( ",-'" );
- gfx_goto( x+3, y-2 );
- gfx_putstr( "`-." );
- gfx_color( BLUE );
- gfx_goto( x-2, y-3 );
- gfx_putchar( ':' );
- gfx_goto( x+3, y-3 );
- gfx_putchar( ':' );
- break;
- case 18:
- default:
- r = (18 - frame) * (18 - frame);
- gfx_color( WHITE );
- gfx_goto( x-1, y-5-r );
- gfx_putstr( ":%%:" );
- gfx_goto( x-1, y-4-r );
- gfx_putstr( "%##%" );
- gfx_color( CYAN );
- gfx_goto( x-2, y-4-r );
- gfx_putchar( ':' );
- gfx_goto( x+3, y-4-r );
- gfx_putchar( ':' );
- gfx_goto( x-2, y-2 );
- gfx_putchar( '\'' );
- gfx_goto( x+3, y-2 );
- gfx_putchar( '`' );
- gfx_color( BLUE );
- gfx_goto( x-3, y-2 );
- gfx_putchar( ':' );
- gfx_goto( x+4, y-2 );
- gfx_putchar( ':' );
- for( i = 0; i <= r; i++ )
- {
- gfx_color( WHITE );
- gfx_goto( x-1, y-3-i );
- gfx_putstr( (i+frame) % 5 ? "####" : "%%%%" );
- gfx_color( CYAN );
- gfx_goto( x-2, y-3-i );
- gfx_putchar( '%' );
- gfx_goto( x+3, y-3-i );
- gfx_putchar( '%' );
- gfx_color( BLUE );
- gfx_goto( x-3, y-3-i );
- gfx_putchar( ':' );
- gfx_goto( x+4, y-3-i );
- gfx_putchar( ':' );
- }
- break;
- }
- }
-
- static void draw_nuke( int x, int y, int frame )
- {
- int r = (29 - frame) * (29 - frame) / 8;
-
- /* Lots of duplicate pixels, but we don't care */
- gfx_color( BLUE );
- draw_circle( x, y, r++, ':' );
- gfx_color( CYAN );
- draw_circle( x, y, r++, '%' );
- gfx_color( WHITE );
- draw_circle( x, y, r++, '#' );
- draw_circle( x, y, r++, '#' );
- }
-
- static void draw_circle( int x, int y, int r, char c )
- {
- int test, dx, dy;
-
- /* Optimized Bresenham. Kick ass. */
- for( test = 0, dx = 0, dy = r ; dx <= dy ; dx++ )
- {
- gfx_putcharTO( x + dx, y + dy / 2, c );
- gfx_putcharTO( x - dx, y + dy / 2, c );
- gfx_putcharTO( x + dx, y - dy / 2, c );
- gfx_putcharTO( x - dx, y - dy / 2, c );
-
- gfx_putcharTO( x + dy, y + dx / 2, c );
- gfx_putcharTO( x - dy, y + dx / 2, c );
- gfx_putcharTO( x + dy, y - dx / 2, c );
- gfx_putcharTO( x - dy, y - dx / 2, c );
-
- test += test > 0 ? dx - dy-- : dx;
- }
- }
|