diff --git a/collide.c b/collide.c index 85c1411..1c14b70 100644 --- a/collide.c +++ b/collide.c @@ -7,7 +7,7 @@ void collide_weapons_tunnel( game *g, weapons *wp, tunnel *t, explosions *ex ) { int i; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { if( wp->y[i] >= 0 ) { @@ -59,47 +59,77 @@ void collide_weapons_aliens( game *g, weapons *wp, aliens *al, explosions *ex ) { int i, j; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { if( wp->y[i] >= 0 ) { int ok = 0; + int r; - for( j = 0; j < ALIENS; j++ ) + switch( wp->type[i] ) { - if( wp->x[i] >= al->x[j] - && wp->x[i] <= al->x[j] + 4 - && wp->y[i] >= al->y[j] - && wp->y[i] <= al->y[j] + 2 ) + case 2: + /* Big nuke */ + r = (34 - wp->n[i]) * (34 - wp->n[i]) / 10; + + for( j = 0; j < ALIENS; j++ ) { - al->life[j]--; - if( al->life[j] == 0 ) + if( al->x[j] < 0 ) + { + continue; + } + + if( (al->x[j] - wp->x[i]) * (al->x[j] - wp->x[i]) + + 4 * (al->y[j] - wp->y[i]) * (al->y[j] - wp->y[i]) + <= r * r ) { + /* Kill alien, not nuke */ + add_explosion( g, ex, al->x[j], al->y[j], 0, 0, 1 ); al->x[j] = -1; al->y[j] = -1; - add_explosion( g, ex, wp->x[i], wp->y[i], 0, 0, 1 ); } - ok = 1; } - else if( wp->x[i] >= al->x[j] - && wp->x[i] <= al->x[j] + 4 - && wp->y[i]+1 >= al->y[j] - && wp->y[i]+1 <= al->y[j] + 2 ) + break; + + case 1: + default: + for( j = 0; j < ALIENS; j++ ) { - al->life[j]--; - if( al->life[j] == 0 ) + if( wp->x[i] >= al->x[j] + && wp->x[i] <= al->x[j] + 4 + && wp->y[i] >= al->y[j] + && wp->y[i] <= al->y[j] + 2 ) { - al->x[j] = -1; - al->y[j] = -1; - add_explosion( g, ex, wp->x[i], wp->y[i]+1, 0, 0, 1 ); + al->life[j]--; + if( al->life[j] == 0 ) + { + al->x[j] = -1; + al->y[j] = -1; + add_explosion( g, ex, wp->x[i], wp->y[i], 0, 0, 1 ); + } + ok = 1; + } + else if( wp->x[i] >= al->x[j] + && wp->x[i] <= al->x[j] + 4 + && wp->y[i]+1 >= al->y[j] + && wp->y[i]+1 <= al->y[j] + 2 ) + { + al->life[j]--; + if( al->life[j] == 0 ) + { + al->x[j] = -1; + al->y[j] = -1; + add_explosion( g, ex, wp->x[i], wp->y[i]+1, 0, 0, 1 ); + } + ok = 1; } - ok = 1; } - } - if( ok ) - { - wp->y[i] = -1; + if( ok ) + { + wp->y[i] = -1; + } + break; } } } diff --git a/common.h b/common.h index 12ea864..6866c49 100644 --- a/common.h +++ b/common.h @@ -1,6 +1,6 @@ #define STARS 50 -#define SHOTS 50 +#define WEAPONS 50 #define ROCKS 10 #define ALIENS 10 #define EXPLOSIONS 20 @@ -17,6 +17,8 @@ # define GFX_WRITE(x) addch(x) #endif +#define GFX_WRITETO(x,y,c) do{ GFX_GOTO(x,y); GFX_WRITE(c); }while(0) + #define GET_RAND(p,q) ((p)+(int)((1.0*((q)-(p)))*rand()/(RAND_MAX+1.0))) typedef struct @@ -54,9 +56,11 @@ typedef struct typedef struct { - int x[SHOTS]; - int y[SHOTS]; - int v[SHOTS]; + int x[WEAPONS]; + int y[WEAPONS]; + int v[WEAPONS]; + int n[WEAPONS]; + int type[WEAPONS]; } weapons; @@ -64,7 +68,7 @@ typedef struct { int x, y; int dir; - int weapon; + int weapon, nuke; } player; @@ -112,7 +116,7 @@ void update_player( game *g, player *p ); void init_weapons( game *g, weapons *wp ); void draw_weapons( game *g, weapons *wp ); void update_weapons( game *g, weapons *wp ); -void add_weapon( game *g, weapons *wp, int x, int y ); +void add_weapon( game *g, weapons *wp, int x, int y, int type ); void init_starfield( game *g, starfield *s ); void draw_starfield( game *g, starfield *s ); diff --git a/explosions.c b/explosions.c index c6fcd99..e3e8200 100644 --- a/explosions.c +++ b/explosions.c @@ -1,12 +1,10 @@ #include -#include #include "common.h" static void draw_small_explosion( int x, int y, int frame ); static void draw_big_explosion( int x, int y, int frame ); -static void draw_huge_explosion( int x, int y, int frame ); void init_explosions( game *g, explosions *ex ) { @@ -85,9 +83,6 @@ void draw_explosions( game *g, explosions *ex ) switch( ex->type[i] ) { - case 2: - draw_huge_explosion( ex->x[i], ex->y[i], ex->n[i] ); - break; case 1: draw_big_explosion( ex->x[i], ex->y[i], ex->n[i] ); break; @@ -308,98 +303,3 @@ static void draw_big_explosion( int x, int y, int frame ) } } -static void draw_circle( int x, int y, float r ); - -static void draw_huge_explosion( int x, int y, int frame ) -{ - float r = 1.5 * (30 - frame); - - GFX_COLOR( BLUE ); - draw_circle( x, y, r ); - - r += 0.7; - - GFX_COLOR( CYAN ); - draw_circle( x, y, r ); - - r += 0.7; - - GFX_COLOR( WHITE ); - draw_circle( x, y, r ); -} - -static void draw_circle( int x, int y, float r ) -{ -#if 1 - float c; - - for( c = 0 ; c <= 90 ; c += 1 ) - { - float dx = 0.5 + r * 2.0 * sin( c * M_PI / 180.0 ); - float dy = 0.5 + r * cos( c * M_PI / 180.0 ); - - GFX_GOTO( x + dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x + dx, y - dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y - dy ); - GFX_WRITE( '#' ); - } -#endif - -#if 0 -int dx,dy,a2,b2, S, T; -float a = r*8, b = r*2; - - a2 = a*a; - b2 = b*b; - dx = 0; - dy = b; - S = a2*(1-2*b) + 2*b2; - T = b2 - 2*a2*(2*b-1); - GFX_GOTO( x + dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x + dx, y - dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y - dy ); - GFX_WRITE( '#' ); - - do - { - if (S<0) - { - S += 2*b2*(2*x+3); - T += 4*b2*(x+1); - dx++; - } - else if (T<0) - { - S += 2*b2*(2*x+3) - 4*a2*(dy-1); - T += 4*b2*(x+1) - 2*a2*(2*dy-3); - dx++; - dy--; - } - else - { - S -= 4*a2*(dy-1); - T -= 2*a2*(2*dy-3); - dy--; - } - GFX_GOTO( x + dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y + dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x + dx, y - dy ); - GFX_WRITE( '#' ); - GFX_GOTO( x - dx, y - dy ); - GFX_WRITE( '#' ); - } - while (dy>0); -#endif - -} - diff --git a/main.c b/main.c index cdeaafa..bc715a2 100644 --- a/main.c +++ b/main.c @@ -98,23 +98,27 @@ static void start_game (game *g) p->dir = -3; break; case 'j': - //if( p->y < g->h - 2 ) p->y += 1; + if( p->y < g->h - 2 ) p->y += 1; break; case 'k': - //if( p->y > 1 ) p->y -= 1; + if( p->y > 1 ) p->y -= 1; break; case 'l': p->dir = 3; break; case '\r': - add_explosion( g, ex, p->x + 2, p->y, 0, 0, 2 ); + if( p->nuke == 0 ) + { + p->nuke = 40; + add_weapon( g, wp, p->x + 2, p->y, 2 ); + } break; case ' ': if( p->weapon == 0 ) { p->weapon = 4; - add_weapon( g, wp, p->x, p->y ); - add_weapon( g, wp, p->x + 5, p->y ); + add_weapon( g, wp, p->x, p->y, 1 ); + add_weapon( g, wp, p->x + 5, p->y, 1 ); } break; } diff --git a/player.c b/player.c index 87e9f2e..d5f1013 100644 --- a/player.c +++ b/player.c @@ -12,6 +12,7 @@ player * create_player( game *g ) p->y = g->h - 3; p->dir = 0; p->weapon = 0; + p->nuke = 0; return p; } @@ -51,6 +52,11 @@ void update_player( game *g, player *p ) p->weapon--; } + if( p->nuke ) + { + p->nuke--; + } + if( p->dir < 0 ) { if( p->dir == -3 && p->x > -2 ) p->x -= 1; diff --git a/weapons.c b/weapons.c index ba41857..3346fa5 100644 --- a/weapons.c +++ b/weapons.c @@ -3,15 +3,20 @@ #include "common.h" +static void draw_nuke( int x, int y, int frame ); +static void draw_circle( int x, int y, int r ); + void init_weapons( game *g, weapons *wp ) { int i; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { wp->x[i] = -1; wp->y[i] = -1; wp->v[i] = 0; + wp->n[i] = 0; + wp->type[i] = 0; } } @@ -19,16 +24,25 @@ void draw_weapons( game *g, weapons *wp ) { int i; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { if( wp->x[i] >= 0 ) { - GFX_COLOR( WHITE ); - GFX_GOTO( wp->x[i], wp->y[i] ); - GFX_WRITE( '|' ); - GFX_COLOR( CYAN ); - GFX_GOTO( wp->x[i], wp->y[i] + 1 ); - GFX_WRITE( '|' ); + switch( wp->type[i] ) + { + case 2: + draw_nuke( wp->x[i], wp->y[i], wp->n[i] ); + break; + case 1: + default: + GFX_COLOR( WHITE ); + GFX_GOTO( wp->x[i], wp->y[i] ); + GFX_WRITE( '|' ); + GFX_COLOR( CYAN ); + GFX_GOTO( wp->x[i], wp->y[i] + 1 ); + GFX_WRITE( '|' ); + break; + } } } } @@ -37,7 +51,7 @@ void update_weapons( game *g, weapons *wp ) { int i; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { if( wp->y[i] < 0 ) { @@ -46,26 +60,76 @@ void update_weapons( game *g, weapons *wp ) } else { - wp->y[i] += wp->v[i]; + switch( wp->type[i] ) + { + case 2: + wp->n[i]--; + if( wp->n[i]-- < 0 ) + { + wp->y[i] = -1; + } + break; + case 1: + default: + wp->y[i] += wp->v[i]; + break; + } /* Check collisions */ } } } -void add_weapon( game *g, weapons *wp, int x, int y ) +void add_weapon( game *g, weapons *wp, int x, int y, int type ) { int i; - for( i = 0; i < SHOTS; i++ ) + for( i = 0; i < WEAPONS; i++ ) { if( wp->y[i] < 0 ) { wp->x[i] = x; wp->y[i] = y; + wp->type[i] = type; wp->v[i] = -2; + wp->n[i] = 30; break; } } } +static void draw_nuke( int x, int y, int frame ) +{ + int r = (34 - frame) * (34 - frame) / 10; + + /* 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 ) +{ + int test, dx, dy; + + /* Optimized Bresenham. Kick ass. */ + for( test = 0, dx = 0, dy = r ; dx <= dy ; dx++ ) + { + GFX_WRITETO( x + dx, y + dy / 2, '#' ); + GFX_WRITETO( x - dx, y + dy / 2, '#' ); + GFX_WRITETO( x + dx, y - dy / 2, '#' ); + GFX_WRITETO( x - dx, y - dy / 2, '#' ); + + GFX_WRITETO( x + dy, y + dx / 2, '#' ); + GFX_WRITETO( x - dy, y + dx / 2, '#' ); + GFX_WRITETO( x + dy, y - dx / 2, '#' ); + GFX_WRITETO( x - dy, y - dx / 2, '#' ); + + test += test > 0 ? dx - dy-- : dx; + } +} +