root/demos/speed/badguys.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lay_attack_wave
  2. init_badguys
  3. shutdown_badguys
  4. update_badguys
  5. draw_badguys

   1 /*
   2  *    SPEED - by Shawn Hargreaves, 1999
   3  *
   4  *    Enemy control routines (attack waves).
   5  */
   6 
   7 #include <math.h>
   8 #include <allegro5/allegro.h>
   9 
  10 #include "speed.h"
  11 
  12 
  13 
  14 /* description of an attack wave */
  15 typedef struct WAVEINFO
  16 {
  17    int count;              /* how many to create */
  18    float delay;            /* how long to delay them */
  19    float delay_rand;       /* random delay factor */
  20    float speed;            /* how fast they move */
  21    float speed_rand;       /* speed random factor */
  22    float move;             /* movement speed */
  23    float move_rand;        /* movement random factor */
  24    float sin_depth;        /* depth of sine wave motion */
  25    float sin_depth_rand;   /* sine depth random factor */
  26    float sin_speed;        /* speed of sine wave motion */
  27    float sin_speed_rand;   /* sine speed random factor */
  28    int split;              /* split into multiple dudes? */
  29    int aggro;              /* attack the player? */
  30    int evade;              /* evade the player? */
  31 } WAVEINFO;
  32 
  33 
  34 
  35 #define END_WAVEINFO       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  36 
  37 
  38 
  39 /* attack wave #1 (straight downwards) */
  40 static WAVEINFO wave1[] =
  41 {
  42    /* c  del  rnd  speed   r  mv r  dp r  sd r  sp ag ev */
  43    {  4, 0.0, 1.0, 0.0015, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0  },
  44    {  2, 0.7, 0.0, 0.0055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  },
  45    {  2, 0.5, 0.0, 0.0045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  },
  46    {  4, 0.0, 1.0, 0.0035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  },
  47    {  4, 0.0, 1.0, 0.0025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  },
  48    END_WAVEINFO
  49 };
  50 
  51 
  52 
  53 /* attack wave #2 (diagonal motion) */
  54 static WAVEINFO wave2[] =
  55 {
  56    /* c  del  rnd  speed   rnd     move    rnd    dp r  sd r  sp ag ev */
  57    {  6, 2.0, 1.0, 0.0025, 0.002,  0.0000, 0.020, 0, 0, 0, 0, 0, 0, 0  },
  58    {  6, 1.2, 1.0, 0.0025, 0.001,  0.0000, 0.010, 0, 0, 0, 0, 0, 0, 0  },
  59    {  6, 0.5, 1.0, 0.0025, 0.000,  0.0000, 0.005, 0, 0, 0, 0, 0, 0, 0  },
  60    {  4, 0.0, 1.0, 0.0025, 0.000, -0.0025, 0.000, 0, 0, 0, 0, 0, 0, 0  },
  61    {  4, 0.0, 1.0, 0.0025, 0.000,  0.0025, 0.000, 0, 0, 0, 0, 0, 0, 0  },
  62    END_WAVEINFO
  63 };
  64 
  65 
  66 
  67 /* attack wave #3 (sine wave motion) */
  68 static WAVEINFO wave3[] =
  69 {
  70    /* c  del  rnd  speed   rnd     mv r  sdepth rnd    sspd   rnd   sp ag ev */
  71    {  4, 0.0, 2.0, 0.0020, 0.0000, 0, 0, 0.005, 0.000, 0.020, 0.00, 1, 0, 0  },
  72    {  4, 1.5, 1.0, 0.0016, 0.0024, 0, 0, 0.002, 0.006, 0.010, 0.03, 0, 0, 0  },
  73    {  4, 1.0, 1.0, 0.0019, 0.0016, 0, 0, 0.003, 0.004, 0.015, 0.02, 0, 0, 0  },
  74    {  4, 0.5, 1.0, 0.0022, 0.0008, 0, 0, 0.004, 0.002, 0.020, 0.01, 0, 0, 0  },
  75    {  4, 0.0, 1.0, 0.0025, 0.0000, 0, 0, 0.005, 0.000, 0.025, 0.00, 0, 0, 0  },
  76    END_WAVEINFO
  77 };
  78 
  79 
  80 
  81 /* attack wave #4 (evade you) */
  82 static WAVEINFO wave4[] =
  83 {
  84    /* c  del  rnd  speed   rnd     mv rnd    dp r  sd r  sp ag ev */
  85    {  4, 0.0, 2.0, 0.0020, 0.0000, 0, 0.000, 0, 0, 0, 0, 1, 0, 1  },
  86    {  3, 1.5, 1.0, 0.0016, 0.0024, 0, 0.010, 0, 0, 0, 0, 0, 0, 1  },
  87    {  3, 1.0, 1.0, 0.0019, 0.0016, 0, 0.001, 0, 0, 0, 0, 0, 0, 1  },
  88    {  4, 0.5, 1.0, 0.0022, 0.0008, 0, 0.000, 0, 0, 0, 0, 0, 0, 1  },
  89    {  4, 0.0, 1.0, 0.0025, 0.0000, 0, 0.000, 0, 0, 0, 0, 0, 0, 1  },
  90    END_WAVEINFO
  91 };
  92 
  93 
  94 
  95 /* attack wave #5 (attack you) */
  96 static WAVEINFO wave5[] =
  97 {
  98    /* c  del  rnd  speed   rnd     mv rnd    sd r  sd r  sp ag ev */
  99    {  4, 0.0, 2.0, 0.0010, 0.0000, 0, 0.000, 0, 0, 0, 0, 1, 1, 0  },
 100    {  3, 1.5, 1.0, 0.0016, 0.0024, 0, 0.010, 0, 0, 0, 0, 0, 1, 0  },
 101    {  3, 1.0, 1.0, 0.0019, 0.0016, 0, 0.001, 0, 0, 0, 0, 0, 1, 0  },
 102    {  3, 0.5, 1.0, 0.0022, 0.0008, 0, 0.000, 0, 0, 0, 0, 0, 1, 0  },
 103    {  4, 0.0, 1.0, 0.0025, 0.0000, 0, 0.000, 0, 0, 0, 0, 0, 1, 0  },
 104    END_WAVEINFO
 105 };
 106 
 107 
 108 
 109 /* attack wave #6 (the boss wave, muahaha) */
 110 static WAVEINFO wave6[] =
 111 {
 112    /* c  del  rnd  speed  rnd    mv rnd   dp rnd    sd rnd   sp ag ev */
 113    {  8, 6.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0,     0, 0,    1, 1, 0  },
 114    {  8, 4.5, 2.0, 0.002, 0.001, 0, 0.00, 0, 0,     0, 0,    1, 0, 1  },
 115    {  8, 3.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0.006, 0, 0.03, 1, 0, 0  },
 116    {  8, 1.5, 2.0, 0.002, 0.001, 0, 0.01, 0, 0,     0, 0,    1, 0, 0  },
 117    {  8, 0.0, 2.0, 0.002, 0.001, 0, 0.00, 0, 0,     0, 0,    1, 0, 0  },
 118    END_WAVEINFO
 119 };
 120 
 121 
 122 
 123 /* list of available attack waves */
 124 static WAVEINFO *waveinfo[] =
 125 {
 126    wave1+4, wave2+4, wave3+4, wave4+4, wave5+4,
 127    wave1+3, wave2+3, wave3+3, wave4+3, wave5+3,
 128    wave1+2, wave2+2, wave3+2, wave4+2, wave5+2,
 129    wave1+1, wave2+1, wave3+1, wave4+1, wave5+1,
 130    wave1+0, wave2+0, wave3+0, wave4+0, wave5+0,
 131    wave6
 132 };
 133 
 134 
 135 
 136 /* info about someone nasty */
 137 typedef struct BADGUY
 138 {
 139    float x;                /* x position */
 140    float y;                /* y position */
 141    float speed;            /* vertical speed */
 142    float move;             /* horizontal motion */
 143    float sin_depth;        /* depth of sine motion */
 144    float sin_speed;        /* speed of sine motion */
 145    int split;              /* whether to split ourselves */
 146    int aggro;              /* whether to attack the player */
 147    int evade;              /* whether to evade the player */
 148    float v;                /* horizontal velocity */
 149    int t;                  /* integer counter */
 150    struct BADGUY *next;
 151 } BADGUY;
 152 
 153 
 154 static BADGUY *evildudes;
 155 
 156 static int finished_counter;
 157 
 158 static int wavenum;
 159 
 160 
 161 
 162 /* creates a new swarm of badguys */
 163 void lay_attack_wave(int reset)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165    WAVEINFO *info;
 166    BADGUY *b;
 167    int i;
 168 
 169    if (reset) {
 170       wavenum = 0;
 171    }
 172    else {
 173       wavenum++;
 174       if (wavenum >= (int)(sizeof(waveinfo)/sizeof(WAVEINFO *)))
 175          wavenum = 0;
 176    }
 177 
 178    info = waveinfo[wavenum];
 179 
 180    while (info->count) {
 181       for (i=0; i<info->count; i++) {
 182          b = malloc(sizeof(BADGUY));
 183 
 184          #define URAND  ((float)(rand() & 255) / 255.0)
 185          #define SRAND  (((float)(rand() & 255) / 255.0) - 0.5)
 186 
 187          b->x = URAND;
 188          b->y = -info->delay - URAND * info->delay_rand;
 189          b->speed = info->speed + URAND * info->speed_rand;
 190          b->move = info->move + SRAND * info->move_rand;
 191          b->sin_depth = info->sin_depth + URAND * info->sin_depth_rand;
 192          b->sin_speed = info->sin_speed + URAND * info->sin_speed_rand;
 193          b->split = info->split;
 194          b->aggro = info->aggro;
 195          b->evade = info->evade;
 196          b->v = 0;
 197          b->t = rand() & 255;
 198 
 199          b->next = evildudes;
 200          evildudes = b;
 201       }
 202 
 203       info++;
 204    }
 205 
 206    finished_counter = 0;
 207 }
 208 
 209 
 210 
 211 /* initialises the badguy functions */
 212 void init_badguys()
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214    evildudes = NULL;
 215 
 216    lay_attack_wave(TRUE);
 217 }
 218 
 219 
 220 
 221 /* closes down the badguys module */
 222 void shutdown_badguys()
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224    BADGUY *b;
 225 
 226    while (evildudes) {
 227       b = evildudes;
 228       evildudes = evildudes->next;
 229       free(b);
 230    }
 231 }
 232 
 233 
 234 
 235 /* updates the badguy position */
 236 int update_badguys()
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238    BADGUY **p = &evildudes;
 239    BADGUY *b = evildudes;
 240    BADGUY *tmp1, *tmp2;
 241    void *bullet;
 242    float x, y, d;
 243    int dead;
 244 
 245    /* testcode: enter clears the level */
 246    if ((cheat) && (key[ALLEGRO_KEY_ENTER])) {
 247       shutdown_badguys();
 248       b = NULL;
 249 
 250       while (key[ALLEGRO_KEY_ENTER])
 251          poll_input_wait();
 252    }
 253 
 254    while (b) {
 255       dead = FALSE;
 256 
 257       if (b->aggro) {
 258          /* attack the player */
 259          d = player_pos() - b->x;
 260 
 261          if (d < -0.5)
 262             d += 1;
 263          else if (d > 0.5)
 264             d -= 1;
 265 
 266          if (b->y < 0.5)
 267             d = -d;
 268 
 269          b->v *= 0.99;
 270          b->v += SGN(d) * 0.00025;
 271       }
 272       else if (b->evade) {
 273          /* evade the player */
 274          if (b->y < 0.75)
 275             d = player_pos() + 0.5;
 276          else
 277             d = b->x;
 278 
 279          if (b->move)
 280             d += SGN(b->move) / 16.0;
 281 
 282          d = find_target(d) - b->x;
 283 
 284          if (d < -0.5)
 285             d += 1;
 286          else if (d > 0.5)
 287             d -= 1;
 288 
 289          b->v *= 0.96;
 290          b->v += SGN(d) * 0.0004;
 291       }
 292 
 293       /* horizontal move */
 294       b->x += b->move + sin(b->t * b->sin_speed) * b->sin_depth + b->v;
 295 
 296       if (b->x < 0)
 297          b->x += 1;
 298       else if (b->x > 1)
 299          b->x -= 1;
 300 
 301       /* vertical move */
 302       b->y += b->speed;
 303 
 304       if ((b->y > 0.5) && (b->y - b->speed <= 0.5) && (b->split)) {
 305          /* split ourselves */
 306          tmp1 = malloc(sizeof(BADGUY));
 307          tmp2 = malloc(sizeof(BADGUY));
 308 
 309          *tmp1 = *tmp2 = *b;
 310 
 311          tmp1->move -= 0.001;
 312          tmp2->move += 0.001;
 313 
 314          b->speed += 0.001;
 315 
 316          tmp1->t = rand() & 255;
 317          tmp2->t = rand() & 255;
 318 
 319          tmp1->next = tmp2;
 320          tmp2->next = evildudes;
 321          evildudes = tmp1;
 322       }
 323 
 324       b->t++;
 325 
 326       if (b->y > 0) {
 327          if (kill_player(b->x, b->y)) {
 328             /* did we hit someone? */
 329             dead = TRUE;
 330          }
 331          else {
 332             /* or did someone else hit us? */
 333             bullet = get_first_bullet(&x, &y);
 334 
 335             while (bullet) {
 336                x = x - b->x;
 337 
 338                if (x < -0.5)
 339                   x += 1;
 340                else if (x > 0.5)
 341                   x -= 1;
 342 
 343                x = ABS(x);
 344 
 345                y = ABS(y - b->y);
 346 
 347                if (x < y)
 348                   d = y/2 + x;
 349                else
 350                   d = x/2 + y;
 351 
 352                if (d < 0.025) {
 353                   kill_bullet(bullet);
 354                   explode(b->x, b->y, 0);
 355                   sfx_explode_alien();
 356                   dead = TRUE;
 357                   break;
 358                }
 359 
 360                bullet = get_next_bullet(bullet, &x, &y);
 361             }
 362          }
 363       }
 364 
 365       /* advance to the next dude */
 366       if (dead) {
 367          *p = b->next;
 368          tmp1 = b;
 369          b = b->next;
 370          free(tmp1);
 371       }
 372       else {
 373          p = &b->next;
 374          b = b->next;
 375       }
 376    }
 377 
 378    if ((!evildudes) && (!player_dying())) {
 379       if (!finished_counter) {
 380          message("Wave Complete");
 381          sfx_ping(0);
 382       }
 383 
 384       finished_counter++;
 385 
 386       if (finished_counter > 64)
 387          return TRUE;
 388    }
 389 
 390    return FALSE;
 391 }
 392 
 393 
 394 
 395 /* draws the badguys */
 396 void draw_badguys(int r, int g, int b, int (*project)(float *f, int *i, int c))
     /* [previous][next][first][last][top][bottom][index][help] */
 397 {
 398    BADGUY *bad = evildudes;
 399    ALLEGRO_COLOR c = makecol(r, g, b);
 400    float shape[12];
 401    int ishape[12];
 402 
 403    while (bad) {
 404       if (bad->y > 0) {
 405          shape[0] = bad->x - 0.02;
 406          shape[1] = bad->y + 0.01;
 407 
 408          shape[2] = bad->x;
 409          shape[3] = bad->y + 0.02;
 410 
 411          shape[4] = bad->x + 0.02;
 412          shape[5] = bad->y + 0.01;
 413 
 414          shape[6] = bad->x + 0.01;
 415          shape[7] = bad->y + 0.005;
 416 
 417          shape[8] = bad->x;
 418          shape[9] = bad->y - 0.015;
 419 
 420          shape[10] = bad->x - 0.01;
 421          shape[11] = bad->y + 0.005;
 422 
 423          if (project(shape, ishape, 12))
 424             polygon(6, ishape, c);
 425       }
 426 
 427       bad = bad->next;
 428    }
 429 }
 430 

/* [previous][next][first][last][top][bottom][index][help] */