* used a cool Bresenham algorithm to draw the nuke circles. * nuke collides with aliens.tags/v0.99.beta14
@@ -7,7 +7,7 @@ void collide_weapons_tunnel( game *g, weapons *wp, tunnel *t, explosions *ex ) | |||||
{ | { | ||||
int i; | int i; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
if( wp->y[i] >= 0 ) | if( wp->y[i] >= 0 ) | ||||
{ | { | ||||
@@ -59,47 +59,77 @@ void collide_weapons_aliens( game *g, weapons *wp, aliens *al, explosions *ex ) | |||||
{ | { | ||||
int i, j; | int i, j; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
if( wp->y[i] >= 0 ) | if( wp->y[i] >= 0 ) | ||||
{ | { | ||||
int ok = 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->x[j] = -1; | ||||
al->y[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; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -1,6 +1,6 @@ | |||||
#define STARS 50 | #define STARS 50 | ||||
#define SHOTS 50 | |||||
#define WEAPONS 50 | |||||
#define ROCKS 10 | #define ROCKS 10 | ||||
#define ALIENS 10 | #define ALIENS 10 | ||||
#define EXPLOSIONS 20 | #define EXPLOSIONS 20 | ||||
@@ -17,6 +17,8 @@ | |||||
# define GFX_WRITE(x) addch(x) | # define GFX_WRITE(x) addch(x) | ||||
#endif | #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))) | #define GET_RAND(p,q) ((p)+(int)((1.0*((q)-(p)))*rand()/(RAND_MAX+1.0))) | ||||
typedef struct | typedef struct | ||||
@@ -54,9 +56,11 @@ typedef struct | |||||
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; | } weapons; | ||||
@@ -64,7 +68,7 @@ typedef struct | |||||
{ | { | ||||
int x, y; | int x, y; | ||||
int dir; | int dir; | ||||
int weapon; | |||||
int weapon, nuke; | |||||
} player; | } player; | ||||
@@ -112,7 +116,7 @@ void update_player( game *g, player *p ); | |||||
void init_weapons( game *g, weapons *wp ); | void init_weapons( game *g, weapons *wp ); | ||||
void draw_weapons( game *g, weapons *wp ); | void draw_weapons( game *g, weapons *wp ); | ||||
void update_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 init_starfield( game *g, starfield *s ); | ||||
void draw_starfield( game *g, starfield *s ); | void draw_starfield( game *g, starfield *s ); | ||||
@@ -1,12 +1,10 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <math.h> | |||||
#include "common.h" | #include "common.h" | ||||
static void draw_small_explosion( int x, int y, int frame ); | 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_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 ) | void init_explosions( game *g, explosions *ex ) | ||||
{ | { | ||||
@@ -85,9 +83,6 @@ void draw_explosions( game *g, explosions *ex ) | |||||
switch( ex->type[i] ) | switch( ex->type[i] ) | ||||
{ | { | ||||
case 2: | |||||
draw_huge_explosion( ex->x[i], ex->y[i], ex->n[i] ); | |||||
break; | |||||
case 1: | case 1: | ||||
draw_big_explosion( ex->x[i], ex->y[i], ex->n[i] ); | draw_big_explosion( ex->x[i], ex->y[i], ex->n[i] ); | ||||
break; | 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 | |||||
} | |||||
@@ -98,23 +98,27 @@ static void start_game (game *g) | |||||
p->dir = -3; | p->dir = -3; | ||||
break; | break; | ||||
case 'j': | case 'j': | ||||
//if( p->y < g->h - 2 ) p->y += 1; | |||||
if( p->y < g->h - 2 ) p->y += 1; | |||||
break; | break; | ||||
case 'k': | case 'k': | ||||
//if( p->y > 1 ) p->y -= 1; | |||||
if( p->y > 1 ) p->y -= 1; | |||||
break; | break; | ||||
case 'l': | case 'l': | ||||
p->dir = 3; | p->dir = 3; | ||||
break; | break; | ||||
case '\r': | 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; | break; | ||||
case ' ': | case ' ': | ||||
if( p->weapon == 0 ) | if( p->weapon == 0 ) | ||||
{ | { | ||||
p->weapon = 4; | 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; | break; | ||||
} | } | ||||
@@ -12,6 +12,7 @@ player * create_player( game *g ) | |||||
p->y = g->h - 3; | p->y = g->h - 3; | ||||
p->dir = 0; | p->dir = 0; | ||||
p->weapon = 0; | p->weapon = 0; | ||||
p->nuke = 0; | |||||
return p; | return p; | ||||
} | } | ||||
@@ -51,6 +52,11 @@ void update_player( game *g, player *p ) | |||||
p->weapon--; | p->weapon--; | ||||
} | } | ||||
if( p->nuke ) | |||||
{ | |||||
p->nuke--; | |||||
} | |||||
if( p->dir < 0 ) | if( p->dir < 0 ) | ||||
{ | { | ||||
if( p->dir == -3 && p->x > -2 ) p->x -= 1; | if( p->dir == -3 && p->x > -2 ) p->x -= 1; | ||||
@@ -3,15 +3,20 @@ | |||||
#include "common.h" | #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 ) | void init_weapons( game *g, weapons *wp ) | ||||
{ | { | ||||
int i; | int i; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
wp->x[i] = -1; | wp->x[i] = -1; | ||||
wp->y[i] = -1; | wp->y[i] = -1; | ||||
wp->v[i] = 0; | 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; | int i; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
if( wp->x[i] >= 0 ) | 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; | int i; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
if( wp->y[i] < 0 ) | if( wp->y[i] < 0 ) | ||||
{ | { | ||||
@@ -46,26 +60,76 @@ void update_weapons( game *g, weapons *wp ) | |||||
} | } | ||||
else | 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 */ | /* 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; | int i; | ||||
for( i = 0; i < SHOTS; i++ ) | |||||
for( i = 0; i < WEAPONS; i++ ) | |||||
{ | { | ||||
if( wp->y[i] < 0 ) | if( wp->y[i] < 0 ) | ||||
{ | { | ||||
wp->x[i] = x; | wp->x[i] = x; | ||||
wp->y[i] = y; | wp->y[i] = y; | ||||
wp->type[i] = type; | |||||
wp->v[i] = -2; | wp->v[i] = -2; | ||||
wp->n[i] = 30; | |||||
break; | 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; | |||||
} | |||||
} | |||||