/* * SPEED - by Shawn Hargreaves, 1999 * * Enemy control routines (attack waves). */ #include #include #include "speed.h" /* description of an attack wave */ typedef struct WAVEINFO { int count; /* how many to create */ float delay; /* how long to delay them */ float delay_rand; /* random delay factor */ float speed; /* how fast they move */ float speed_rand; /* speed random factor */ float move; /* movement speed */ float move_rand; /* movement random factor */ float sin_depth; /* depth of sine wave motion */ float sin_depth_rand; /* sine depth random factor */ float sin_speed; /* speed of sine wave motion */ float sin_speed_rand; /* sine speed random factor */ int split; /* split into multiple dudes? */ int aggro; /* attack the player? */ int evade; /* evade the player? */ } WAVEINFO; #define END_WAVEINFO { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* attack wave #1 (straight downwards) */ static WAVEINFO wave1[] = { /* c del rnd speed r mv r dp r sd r sp ag ev */ { 4, 0.0, 1.0, 0.0015, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, { 2, 0.7, 0.0, 0.0055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2, 0.5, 0.0, 0.0045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4, 0.0, 1.0, 0.0035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4, 0.0, 1.0, 0.0025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, END_WAVEINFO }; /* attack wave #2 (diagonal motion) */ static WAVEINFO wave2[] = { /* c del rnd speed rnd move rnd dp r sd r sp ag ev */ { 6, 2.0, 1.0, 0.0025, 0.002, 0.0000, 0.020, 0, 0, 0, 0, 0, 0, 0 }, { 6, 1.2, 1.0, 0.0025, 0.001, 0.0000, 0.010, 0, 0, 0, 0, 0, 0, 0 }, { 6, 0.5, 1.0, 0.0025, 0.000, 0.0000, 0.005, 0, 0, 0, 0, 0, 0, 0 }, { 4, 0.0, 1.0, 0.0025, 0.000, -0.0025, 0.000, 0, 0, 0, 0, 0, 0, 0 }, { 4, 0.0, 1.0, 0.0025, 0.000, 0.0025, 0.000, 0, 0, 0, 0, 0, 0, 0 }, END_WAVEINFO }; /* attack wave #3 (sine wave motion) */ static WAVEINFO wave3[] = { /* c del rnd speed rnd mv r sdepth rnd sspd rnd sp ag ev */ { 4, 0.0, 2.0, 0.0020, 0.0000, 0, 0, 0.005, 0.000, 0.020, 0.00, 1, 0, 0 }, { 4, 1.5, 1.0, 0.0016, 0.0024, 0, 0, 0.002, 0.006, 0.010, 0.03, 0, 0, 0 }, { 4, 1.0, 1.0, 0.0019, 0.0016, 0, 0, 0.003, 0.004, 0.015, 0.02, 0, 0, 0 }, { 4, 0.5, 1.0, 0.0022, 0.0008, 0, 0, 0.004, 0.002, 0.020, 0.01, 0, 0, 0 }, { 4, 0.0, 1.0, 0.0025, 0.0000, 0, 0, 0.005, 0.000, 0.025, 0.00, 0, 0, 0 }, END_WAVEINFO }; /* attack wave #4 (evade you) */ static WAVEINFO wave4[] = { /* c del rnd speed rnd mv rnd dp r sd r sp ag ev */ { 4, 0.0, 2.0, 0.0020, 0.0000, 0, 0.000, 0, 0, 0, 0, 1, 0, 1 }, { 3, 1.5, 1.0, 0.0016, 0.0024, 0, 0.010, 0, 0, 0, 0, 0, 0, 1 }, { 3, 1.0, 1.0, 0.0019, 0.0016, 0, 0.001, 0, 0, 0, 0, 0, 0, 1 }, { 4, 0.5, 1.0, 0.0022, 0.0008, 0, 0.000, 0, 0, 0, 0, 0, 0, 1 }, { 4, 0.0, 1.0, 0.0025, 0.0000, 0, 0.000, 0, 0, 0, 0, 0, 0, 1 }, END_WAVEINFO }; /* attack wave #5 (attack you) */ static WAVEINFO wave5[] = { /* c del rnd speed rnd mv rnd sd r sd r sp ag ev */ { 4, 0.0, 2.0, 0.0010, 0.0000, 0, 0.000, 0, 0, 0, 0, 1, 1, 0 }, { 3, 1.5, 1.0, 0.0016, 0.0024, 0, 0.010, 0, 0, 0, 0, 0, 1, 0 }, { 3, 1.0, 1.0, 0.0019, 0.0016, 0, 0.001, 0, 0, 0, 0, 0, 1, 0 }, { 3, 0.5, 1.0, 0.0022, 0.0008, 0, 0.000, 0, 0, 0, 0, 0, 1, 0 }, { 4, 0.0, 1.0, 0.0025, 0.0000, 0, 0.000, 0, 0, 0, 0, 0, 1, 0 }, END_WAVEINFO }; /* attack wave #6 (the boss wave, muahaha) */ static WAVEINFO wave6[] = { /* c del rnd speed rnd mv rnd dp rnd sd rnd sp ag ev */ { 8, 6.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0, 0, 0, 1, 1, 0 }, { 8, 4.5, 2.0, 0.002, 0.001, 0, 0.00, 0, 0, 0, 0, 1, 0, 1 }, { 8, 3.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0.006, 0, 0.03, 1, 0, 0 }, { 8, 1.5, 2.0, 0.002, 0.001, 0, 0.01, 0, 0, 0, 0, 1, 0, 0 }, { 8, 0.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0, 0, 0, 1, 0, 0 }, END_WAVEINFO }; /* list of available attack waves */ static WAVEINFO *waveinfo[] = { wave1+4, wave2+4, wave3+4, wave4+4, wave5+4, wave1+3, wave2+3, wave3+3, wave4+3, wave5+3, wave1+2, wave2+2, wave3+2, wave4+2, wave5+2, wave1+1, wave2+1, wave3+1, wave4+1, wave5+1, wave1+0, wave2+0, wave3+0, wave4+0, wave5+0, wave6 }; /* info about someone nasty */ typedef struct BADGUY { float x; /* x position */ float y; /* y position */ float speed; /* vertical speed */ float move; /* horizontal motion */ float sin_depth; /* depth of sine motion */ float sin_speed; /* speed of sine motion */ int split; /* whether to split ourselves */ int aggro; /* whether to attack the player */ int evade; /* whether to evade the player */ float v; /* horizontal velocity */ int t; /* integer counter */ struct BADGUY *next; } BADGUY; static BADGUY *evildudes; static int finished_counter; static int wavenum; /* creates a new swarm of badguys */ void lay_attack_wave(int reset) { WAVEINFO *info; BADGUY *b; int i; if (reset) { wavenum = 0; } else { wavenum++; if (wavenum >= (int)(sizeof(waveinfo)/sizeof(WAVEINFO *))) wavenum = 0; } info = waveinfo[wavenum]; while (info->count) { for (i=0; icount; i++) { b = malloc(sizeof(BADGUY)); #define URAND ((float)(rand() & 255) / 255.0) #define SRAND (((float)(rand() & 255) / 255.0) - 0.5) b->x = URAND; b->y = -info->delay - URAND * info->delay_rand; b->speed = info->speed + URAND * info->speed_rand; b->move = info->move + SRAND * info->move_rand; b->sin_depth = info->sin_depth + URAND * info->sin_depth_rand; b->sin_speed = info->sin_speed + URAND * info->sin_speed_rand; b->split = info->split; b->aggro = info->aggro; b->evade = info->evade; b->v = 0; b->t = rand() & 255; b->next = evildudes; evildudes = b; } info++; } finished_counter = 0; } /* initialises the badguy functions */ void init_badguys() { evildudes = NULL; lay_attack_wave(TRUE); } /* closes down the badguys module */ void shutdown_badguys() { BADGUY *b; while (evildudes) { b = evildudes; evildudes = evildudes->next; free(b); } } /* updates the badguy position */ int update_badguys() { BADGUY **p = &evildudes; BADGUY *b = evildudes; BADGUY *tmp1, *tmp2; void *bullet; float x, y, d; int dead; /* testcode: enter clears the level */ if ((cheat) && (key[KEY_ENTER])) { shutdown_badguys(); b = NULL; while (key[KEY_ENTER]) poll_keyboard(); } while (b) { dead = FALSE; if (b->aggro) { /* attack the player */ d = player_pos() - b->x; if (d < -0.5) d += 1; else if (d > 0.5) d -= 1; if (b->y < 0.5) d = -d; b->v *= 0.99; b->v += SGN(d) * 0.00025; } else if (b->evade) { /* evade the player */ if (b->y < 0.75) d = player_pos() + 0.5; else d = b->x; if (b->move) d += SGN(b->move) / 16.0; d = find_target(d) - b->x; if (d < -0.5) d += 1; else if (d > 0.5) d -= 1; b->v *= 0.96; b->v += SGN(d) * 0.0004; } /* horizontal move */ b->x += b->move + sin(b->t * b->sin_speed) * b->sin_depth + b->v; if (b->x < 0) b->x += 1; else if (b->x > 1) b->x -= 1; /* vertical move */ b->y += b->speed; if ((b->y > 0.5) && (b->y - b->speed <= 0.5) && (b->split)) { /* split ourselves */ tmp1 = malloc(sizeof(BADGUY)); tmp2 = malloc(sizeof(BADGUY)); *tmp1 = *tmp2 = *b; tmp1->move -= 0.001; tmp2->move += 0.001; b->speed += 0.001; tmp1->t = rand() & 255; tmp2->t = rand() & 255; tmp1->next = tmp2; tmp2->next = evildudes; evildudes = tmp1; } b->t++; if (b->y > 0) { if (kill_player(b->x, b->y)) { /* did we hit someone? */ dead = TRUE; } else { /* or did someone else hit us? */ bullet = get_first_bullet(&x, &y); while (bullet) { x = x - b->x; if (x < -0.5) x += 1; else if (x > 0.5) x -= 1; x = ABS(x); y = ABS(y - b->y); if (x < y) d = y/2 + x; else d = x/2 + y; if (d < 0.025) { kill_bullet(bullet); explode(b->x, b->y, 0); sfx_explode_alien(); dead = TRUE; break; } bullet = get_next_bullet(bullet, &x, &y); } } } /* advance to the next dude */ if (dead) { *p = b->next; tmp1 = b; b = b->next; free(tmp1); } else { p = &b->next; b = b->next; } } if ((!evildudes) && (!player_dying())) { if (!finished_counter) { message("Wave Complete"); sfx_ping(0); } finished_counter++; if (finished_counter > 64) return TRUE; } return FALSE; } /* draws the badguys */ void draw_badguys(BITMAP *bmp, int r, int g, int b, int (*project)(float *f, int *i, int c)) { BADGUY *bad = evildudes; int c = makecol(r, g, b); float shape[12]; int ishape[12]; while (bad) { if (bad->y > 0) { shape[0] = bad->x - 0.02; shape[1] = bad->y + 0.01; shape[2] = bad->x; shape[3] = bad->y + 0.02; shape[4] = bad->x + 0.02; shape[5] = bad->y + 0.01; shape[6] = bad->x + 0.01; shape[7] = bad->y + 0.005; shape[8] = bad->x; shape[9] = bad->y - 0.015; shape[10] = bad->x - 0.01; shape[11] = bad->y + 0.005; if (project(shape, ishape, 12)) polygon(bmp, 6, ishape, c); } bad = bad->next; } }