Want more features on Pastebin? Sign Up, it's FREE!
Guest

Awei Dragon's [partial] source (alpha) by blueshogun96

By: a guest on Jan 16th, 2012  |  syntax: C  |  size: 80.64 KB  |  views: 47  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include "platform.h"
  2. #include "fastfile.h"
  3. #include "ogldrv.h"
  4. #include "aldrv.h"
  5. #include "tgaLoader.h"
  6. #include "vmath.h"
  7. #include "game.h"
  8. #include "gold.h"
  9. #include "input.h"
  10. #include "texfont.h"
  11. #include "menu.h"
  12. #include "spline.h"
  13. #include "wavstream.h"
  14.  
  15.  
  16. /* Enemy types */
  17. #define ENEMY_PARTICLE          0
  18. #define ENEMY_REDDRAGON         1
  19. #define ENEMY_GREENDRAGON       2
  20. #define ENEMY_BLUEDRAGON        3
  21. #define ENEMY_BLACKDRAGON       4
  22. #define ENEMY_WATERDRAGON       5
  23. #define ENEMY_FAIRY                     6
  24. #define ENEMY_PHOENIX           7
  25. #define ENEMY_SQUID                     8
  26. #define ENEMY_SEASERPENT        9
  27. #define ENEMY_TANK                      10
  28. #define ENEMY_ZEPPELIN          11
  29. #define ENEMY_DRONE                     12
  30. #define ENEMY_SUPERDRAGON       13
  31.  
  32. /* Boss types */
  33. #define BOSS_MASK                       0
  34. #define BOSS_SQUID                      1
  35. #define BOSS_BLUEDEATH          2
  36. #define BOSS_AIRSHIP            3
  37. #define BOSS_REAPER                     4
  38.  
  39. /* Power up types */
  40. #define POWER_CRYSTAL1          1
  41. #define POWER_CRYSTAL2          2
  42. #define POWER_CRYSTAL3          3
  43. #define POWER_HEART1            4
  44. #define POWER_HEART2            5
  45.  
  46.  
  47. int     game_state = GAME_STATE_INTRO1;
  48. int menu_state = MENU_STATE_TITLE;     
  49. int     score = 0;
  50. int level = 1;
  51. int boss_mode = No;
  52. int ingame_fade = -1;
  53. int bgm_fade = No;
  54. char bgm_next_track[16] = "";
  55. int bgm_volume = 10;    /* 10=loudest,0=silent */
  56. int sfx_volume = 10;
  57.  
  58.  
  59. float scroll_speed = 0.5f;      /* Ground scroll speed */
  60. int       background = 0;               /* Background image number */
  61. int       fps_limit = 60;               /* FPS cap (varies depending on game speed */
  62.                                                         /* and halves when too many sprites are ingame */
  63. int       game_speed = 100;             /* Game movement speed */
  64. int   active_shoots = 0;        /* Number of active shoots in the game */
  65.  
  66. BYTE                                    keys[256];
  67. struct vec2d_t                  ch;
  68. struct mouse_t                  mouse;
  69. struct dragon_t                 dragon;
  70. struct lock_t                   locks[MAX_LOCKS];
  71. struct enemy_t                  enemies[MAX_ENEMIES];
  72. struct boss_t                   boss;
  73. struct enemyshoot_t             enemyshoots[MAX_ENEMYSHOOTS];
  74. struct guard_t                  guard;
  75. int                                             overdrive_timer = 0;
  76. struct powerup_t                powerups[4];
  77. struct smoke_t                  smoke[MAX_SMOKE];
  78. unsigned int                    textures[MAX_TEXTURES];
  79. struct sound_t                  sfx[MAX_SOUNDFX];
  80. struct font_t                   fonts[7];
  81. struct homingblast_t    homingblasts[MAX_HOMINGBLASTS];
  82. struct fullautoblast_t  fullautoblasts[MAX_FULLAUTOBLASTS];
  83. struct explosion_t              explosions[MAX_EXPLOSIONS];
  84. struct vec2d_t                  trees[8], rocks[8], clouds[3];
  85. struct wave_stream              bgm;
  86. unsigned int                    render_target = 0;
  87.  
  88. #if 1
  89. struct spline_t spline;
  90. #endif
  91.  
  92. char* tex_files[] =
  93. {
  94.         "aircrft1.tga",
  95.         "aircrft2.tga",
  96.         "bkg1.tga",
  97.         "bkg2.tga",
  98.         "bkg3.tga",
  99.         "bkg4.tga",
  100.         "bkg5.tga",
  101.         "bkg6.tga",
  102.         "bkg7.tga",
  103.         "blade1.tga",
  104.         "blade2.tga",
  105.         "bomb.tga",
  106.         "boss1.tga",
  107.         "boss2.tga",
  108.         "boss3.tga",
  109.         "boss4.tga",
  110.         "boss5.tga",
  111.         "blade1.tga",
  112.         "blade2.tga",
  113.         "cloud1.tga",
  114.         "cloud2.tga",
  115.         "cloud3.tga",
  116.         "cross1.tga",
  117.         "cross2.tga",
  118.         "desc1.tga",
  119.         "desc2.tga",
  120.         "desc3.tga",
  121.         "diamond1.tga",
  122.         "diamond2.tga",
  123.         "diamond3.tga",
  124.         "dirt1a.tga",
  125.         "dirt1b.tga",
  126.         "dragon1.tga",
  127.         "dragon2.tga",
  128.         "dragon3.tga",
  129.         "dragon4.tga",
  130.         "drone.tga",
  131.         "expl1.tga",
  132.         "expl2.tga",
  133.         "fairy.tga",
  134.         "fbgreen.tga",
  135.         "fbred.tga",
  136.         "firebal1.tga",
  137.         "firebal2.tga",
  138.         "firebal3.tga",
  139.         "firebird.tga",
  140.         "flare0.tga",
  141.         "flare.tga",
  142.         "gold.tga",
  143.         "grass1a.tga",
  144.         "grass1b.tga",
  145.         "guard.tga",
  146.         "hblast2.tga",
  147.         "hblast.tga",
  148.         "heart1.tga",
  149.         "heart2.tga",
  150.         "hero.tga",
  151.         "intile1.tga",
  152.         "intile2.tga",
  153.         "intile2d.tga",
  154.         "intile3.tga",
  155.         "intile3d.tga",
  156.         "palmtree.tga",
  157.         "particle.tga",
  158.         "phoenix.tga",
  159.         "pinetree.tga",
  160.         "plasma1.tga",
  161.         "plasma2.tga",
  162.         "rock.tga",
  163.         "sand1a.tga",
  164.         "sand1b.tga",
  165.         "sdragon.tga",
  166.         "shogun3d.tga",
  167.         "shot1.tga",
  168.         "shot2.tga",
  169.         "shot.tga",
  170.         "smoke.tga",
  171.         "sparkle.tga",
  172.         "squid.tga",
  173.         "sserpent.tga",
  174.         "tank.tga",
  175.         "title1.tga",
  176.         "title2.tga",
  177.         "water1a.tga",
  178.         "water1b.tga",
  179.         "zeppelin.tga",
  180. };
  181.  
  182. int tex_file_sizes[MAX_TEXTURES];
  183.  
  184. char* sfx_files[] =
  185. {
  186.         "crystal3.wav",
  187.         "firefa.wav",
  188.         "hblast.wav",
  189.         "lock8.wav",
  190.         "mmove.wav",
  191.         "msel.wav"
  192.         "woosh.wav",
  193. };
  194.  
  195. #if 0
  196. int sfx_file_sizes[MAX_SOUNDFX] =
  197. {
  198.         22134,  /* crystal.wav */
  199.         6376,   /* firefa.wav */
  200.         91674,  /* hblast.wav */
  201.         43280,  /* mmove.wav */
  202.         38780,  /* msel.wav */
  203. };
  204. #else
  205. int sfx_file_sizes[MAX_SOUNDFX];
  206. #endif
  207.  
  208. unsigned int get_texture( char* texname );
  209. int active_homing_blasts();
  210. void activate_explosion( int expl_id, float x, float y, int type );
  211. void give_possible_powerup( float x, float y );
  212. void reset_smoke_puffs();
  213. void add_smoke_puff( float x, float y, int type );
  214.  
  215. void update_crosshair_position()
  216. {
  217.         get_crosshair_position( &ch.x, &ch.y );
  218. }
  219.  
  220. void reset_dragon()
  221. {
  222.         /* Reset dragon values */
  223.         dragon.width = 106.0f/2.0f;
  224.         dragon.height = 149.0f/2.0f;
  225.         dragon.x = ( 640.0f / 2.0f ) - ( dragon.width / 2.0f );
  226.         dragon.y = ( 480.0f / 2.0f ) - ( dragon.height / 2.0f );
  227.         dragon.vx = 5.0f;
  228.         dragon.vy = 5.0f;
  229.         dragon.energy = 100;
  230.         dragon.max_energy = 100;
  231.         dragon.attack_mode = 1;
  232.         dragon.powers[0] = Yes;
  233.         dragon.powers[1] = Yes;
  234.         dragon.powers[2] = Yes;
  235.         dragon.inv_t = 0;
  236. }
  237.  
  238. void reset_enemies()
  239. {
  240.         int i = 0;
  241.  
  242.         /* Reset all enemies to dead and with no locks */
  243.         while( i < MAX_ENEMIES )
  244.         {
  245.                 enemies[i].dead = 1;
  246.                 enemies[i].dying = No;
  247.                 enemies[i].lock = -1;
  248.                 enemies[i].type = 0;
  249.                 enemies[i].movement = EMOVEMENT_STATIONARY;
  250.                 enemies[i].line = 0;
  251.                 enemies[i].energy = 1;
  252.                 i++;
  253.         }
  254.  
  255. #if 0
  256.         /* Test: Create one enemy (particle) */
  257.         /*enemies[0].dead = 0;
  258.         enemies[0].frame = 0;
  259.         enemies[0].type = ENEMY_PARTICLE;
  260.         enemies[0].x = 320.0f;
  261.         enemies[0].y = 150.0f;
  262.         enemies[0].sx = 32.0f;
  263.         enemies[0].sy = 32.0f;
  264.         enemies[0].max_frame = 29;
  265.         enemies[0].timer = 0;
  266.         enemies[0].max_timer = 0;
  267.         enemies[0].energy = 1;
  268.  
  269.         enemies[1].dead = 0;
  270.         enemies[1].frame = 0;
  271.         enemies[1].type = ENEMY_REDDRAGON;
  272.         enemies[1].x = 375.0f;
  273.         enemies[1].y = 120.0f;
  274.         enemies[1].sx = 96.0f;
  275.         enemies[1].sy = 64.0f;
  276.         enemies[1].max_frame = 3;
  277.         enemies[1].timer = 0;
  278.         enemies[1].max_timer = 15;
  279.         enemies[1].energy = 5;
  280.  
  281.         enemies[2].dead = 0;
  282.         enemies[2].frame = 0;
  283.         enemies[2].type = ENEMY_GREENDRAGON;
  284.         enemies[2].x = 275.0f;
  285.         enemies[2].y = 120.0f;
  286.         enemies[2].sx = 96.0f;
  287.         enemies[2].sy = 64.0f;
  288.         enemies[2].max_frame = 3;
  289.         enemies[2].timer = 0;
  290.         enemies[2].max_timer = 15;
  291.         enemies[2].energy = 5;
  292.  
  293.         enemies[3].dead = 0;
  294.         enemies[3].frame = 0;
  295.         enemies[3].type = ENEMY_BLACKDRAGON;
  296.         enemies[3].x = 325.0f;
  297.         enemies[3].y = 90.0f;
  298.         enemies[3].sx = 96.0f;
  299.         enemies[3].sy = 64.0f;
  300.         enemies[3].max_frame = 3;
  301.         enemies[3].timer = 0;
  302.         enemies[3].max_timer = 15;
  303.         enemies[3].energy = 5;
  304.  
  305.         enemies[4].dead = 0;
  306.         enemies[4].frame = 0;
  307.         enemies[4].type = ENEMY_FAIRY;
  308.         enemies[4].x = 405.0f;
  309.         enemies[4].y = 40.0f;
  310.         enemies[4].sx = 56.0f;
  311.         enemies[4].sy = 62.0f;
  312.         enemies[4].max_frame = 1;
  313.         enemies[4].timer = 0;
  314.         enemies[4].max_timer = 0;
  315.         enemies[0].energy = 1;*/
  316.  
  317.         enemies[5].dead = 0;
  318.         enemies[5].frame = 0;
  319.         enemies[5].type = ENEMY_FAIRY;
  320.         enemies[5].x = spline.points[spline.start_point].x;
  321.         enemies[5].y = spline.points[spline.start_point].y;
  322.         enemies[5].sx = 56.0f;
  323.         enemies[5].sy = 62.0f;
  324.         enemies[5].max_frame = 1;
  325.         enemies[5].timer = 0;
  326.         enemies[5].max_timer = 0;
  327.         enemies[5].movement = EMOVEMENT_SPLINE;
  328.  
  329.         enemies[6].dead = 0;
  330.         enemies[6].dying = 0;
  331.         enemies[6].frame = 0;
  332.         enemies[6].type = ENEMY_ZEPPELIN;
  333.         enemies[6].x = 320.0f;
  334.         enemies[6].y = 150.0f;
  335.         enemies[6].sx = 76.0f;
  336.         enemies[6].sy = 100.0f;
  337.         enemies[6].max_frame = 1;
  338.         enemies[6].timer = 0;
  339.         enemies[6].max_timer = 0;
  340.         enemies[6].energy = EMAX_ZEPPELIN;
  341.  
  342. /*      enemies[7].dead = 0;
  343.         enemies[7].dying = 0;
  344.         enemies[7].frame = 0;
  345.         enemies[7].type = ENEMY_TANK;
  346.         enemies[7].x = 320.0f;
  347.         enemies[7].y = 0.0f;
  348.         enemies[7].sx = 84.0f;
  349.         enemies[7].sy = 91.0f;
  350.         enemies[7].max_frame = 1;
  351.         enemies[7].timer = 0;
  352.         enemies[7].max_timer = 0;
  353.         enemies[7].energy = EMAX_TANK;
  354.         enemies[7].rot = 180.0f;        // /* Turn completely around */
  355.         /*enemies[7].movement = EMOVEMENT_STILL;*/
  356.  
  357.         enemies[8].dead = 0;
  358.         enemies[8].dying = 0;
  359.         enemies[8].frame = 0;
  360.         enemies[8].type = ENEMY_DRONE;
  361.         enemies[8].x = 280.0f;
  362.         enemies[8].y = 100.0f;
  363.         enemies[8].sx = 16.0f;
  364.         enemies[8].sy = 16.0f;
  365.         enemies[8].max_frame = 1;
  366.         enemies[8].timer = 0;
  367.         enemies[8].max_timer = 0;
  368.         enemies[8].energy = 1;
  369.  
  370.         enemies[9].dead = 0;
  371.         enemies[9].dying = 0;
  372.         enemies[9].frame = 0;
  373.         enemies[9].type = ENEMY_DRONE;
  374.         enemies[9].x = 360.0f;
  375.         enemies[9].y = 100.0f;
  376.         enemies[9].sx = 16.0f;
  377.         enemies[9].sy = 16.0f;
  378.         enemies[9].max_frame = 1;
  379.         enemies[9].timer = 0;
  380.         enemies[9].max_timer = 0;
  381.         enemies[9].energy = 1;
  382.  
  383.         enemies[10].dead = 0;
  384.         enemies[10].dying = 0;
  385.         enemies[10].frame = 0;
  386.         enemies[10].type = ENEMY_DRONE;
  387.         enemies[10].x = 320.0f;
  388.         enemies[10].y = 80.0f;
  389.         enemies[10].sx = 16.0f;
  390.         enemies[10].sy = 16.0f;
  391.         enemies[10].max_frame = 1;
  392.         enemies[10].timer = 0;
  393.         enemies[10].max_timer = 0;
  394.         enemies[10].energy = 1;
  395.  
  396.         /*i = find_inactive_lock();
  397.         if( i != -1 )
  398.         {
  399.                 enemies[0].lock = i;
  400.                 activate_lock( i, enemies[0].x, enemies[0].y );
  401.         }*/
  402. #endif
  403. }
  404.  
  405. int get_enemy_point_value( int type )
  406. {
  407.         switch( type )
  408.         {
  409.         case ENEMY_REDDRAGON:
  410.         case ENEMY_GREENDRAGON:
  411.         case ENEMY_BLUEDRAGON:
  412.         case ENEMY_BLACKDRAGON:
  413.         case ENEMY_WATERDRAGON:
  414.                 return 100;
  415.  
  416.         case ENEMY_FAIRY:
  417.                 return 25;
  418.  
  419.         case ENEMY_PHOENIX:
  420.         case ENEMY_SQUID:
  421.         case ENEMY_SEASERPENT:
  422.                 return 50;
  423.  
  424.         case ENEMY_ZEPPELIN:
  425.         case ENEMY_TANK:
  426.                 return 150;
  427.  
  428.         case ENEMY_DRONE:
  429.                 return 10;
  430.  
  431.         case ENEMY_SUPERDRAGON:
  432.                 return 300;
  433.         }
  434.  
  435.         return 0;
  436. }
  437.  
  438. void kill_enemy( struct enemy_t* e, int expl_sfx )
  439. {
  440.         int expl = 0;
  441.  
  442.         /* Okay, it looks like we have a hit here. Now kill this targetable
  443.            entity and deactivate this homing blast */
  444.         e->dead = Yes;
  445.  
  446.         /* Increase the user's score */
  447.         score += get_enemy_point_value( e->type );
  448.  
  449.         /* Do explosion and sound effects */
  450.         play_sound_effect_static( &sfx[expl_sfx], 0 );
  451.         expl = find_inactive_explosion();
  452.         if( expl != -1 )
  453.         {
  454.                 activate_explosion( expl, e->x, e->y, 0 );
  455.         }
  456.  
  457.         /* Award the user with a gold peice */
  458.         add_gold_peice( e->x, e->y );
  459.  
  460.         /* Possible powerup time */
  461.         give_possible_powerup( e->x, e->y );
  462. }
  463.  
  464. void add_new_enemy_shoot( float x, float y, float speed, int type );
  465.  
  466. void update_drone( struct enemy_t* e )
  467. {
  468.         static int delay = 0;
  469.  
  470.         /* Every 10 frames, make the drones shoot */
  471.         if( ++delay == 4 )
  472.         {
  473.                 add_new_enemy_shoot( e->x, e->y, 2.0f, 0 );
  474.                 delay = 0;
  475.         }      
  476. }
  477.  
  478. void reset_all_locks( int reset_enemy_locks )
  479. {
  480.         int i = 0;
  481.  
  482.         /* Reset all lock values */
  483.         memset( locks, 0, sizeof( struct lock_t ) );
  484.        
  485.         while( i < MAX_LOCKS )
  486.         {
  487.                 locks[i].active = 0;
  488.                 locks[i].size = 500.0f;
  489.                 i++;
  490.         }
  491.  
  492.         /* Remove locks from all enemies if necessary */
  493.         if( reset_enemy_locks )
  494.         {
  495.                 i = 0;
  496.  
  497.                 while( i < MAX_ENEMIES )
  498.                 {
  499.                         enemies[i].lock = -1;
  500.                         i++;
  501.                 }
  502.         }
  503. }
  504.  
  505. void reset_lock_to_inactive( int id )
  506. {
  507.         locks[id].active = 0;
  508.         locks[id].size = 500.0f;
  509.         locks[id].flash = 0;
  510. }
  511.  
  512. int find_inactive_lock()
  513. {
  514.         /* Search for an inactive lock.  If one is free, return the id number
  515.            of that lock and let the caller activate it and track it's position.
  516.            If not, return -1 for no inactive lock. */
  517.         int i = 0;
  518.  
  519.         while( i < MAX_LOCKS )
  520.         {
  521.                 if( !locks[i].active )
  522.                         return i;
  523.  
  524.                 i++;
  525.         }
  526.  
  527.         return -1;
  528. }
  529.  
  530. int active_locks_available()
  531. {
  532.         /* Search for any active locks and return the number of active locks. */
  533.         int i = 0;
  534.         int lock_count = 0;
  535.  
  536.         while( i < MAX_LOCKS )
  537.         {
  538.                 if( locks[i].active )
  539.                         lock_count++;
  540.  
  541.                 i++;
  542.         }
  543.  
  544.         return lock_count;
  545. }
  546.  
  547. void activate_lock( int id, float x, float y )
  548. {
  549.         locks[id].active = 1;
  550.         locks[id].x = x;
  551.         locks[id].y = y;
  552. }
  553.  
  554. void draw_active_locks()
  555. {
  556.         int i;
  557.  
  558.         enable_2d();
  559.        
  560.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  561.  
  562.         wireframe( Yes );
  563.  
  564.         for( i = 0; i < MAX_LOCKS; i++ )
  565.         {
  566.                 if( locks[i].active )
  567.                 {
  568.                         float size = locks[i].size;
  569.  
  570.                         push_pos();
  571.                         translate( locks[i].x, locks[i].y );
  572.                         rotate( locks[i].rotz );
  573.                         if( locks[i].flash == 0 )
  574.                                 draw_quad( 0, -size/2.0f, -size/2.0f, size, size );// size += 5.0f;
  575.                         pop_pos();
  576.                 }
  577.         }
  578.  
  579.         wireframe( No );
  580.  
  581.         disable_2d();
  582. }
  583.  
  584. void update_active_locks()
  585. {
  586.         int i = 0;
  587.  
  588.         while( i < MAX_LOCKS )
  589.         {
  590.                 if( locks[i].active )
  591.                 {
  592.                         locks[i].rotz += 4.0f;
  593.                         locks[i].size -= 15.0f;
  594.  
  595.                         if( locks[i].size < 30.0f )
  596.                                 locks[i].size = 30.0f;
  597.                 }
  598.  
  599.                 if( locks[i].size == 30.0f )
  600.                 {
  601.                         locks[i].rotz = 0.0f;
  602.                         locks[i].flash++;
  603.  
  604.                         if( locks[i].flash > 5 )
  605.                                 locks[i].flash = 0;
  606.                 }
  607.  
  608.                 i++;
  609.         }
  610.  
  611.         /* Update the position of each active lock with the position of
  612.            that particular targetable entity */
  613.         i = 0;
  614.  
  615.         while( i < MAX_LOCKS )
  616.         {
  617.                 if( locks[i].active )
  618.                 {
  619.                         locks[i].x = enemies[locks[i].owner].x;
  620.                         locks[i].y = enemies[locks[i].owner].y;
  621.                 }
  622.  
  623.                 i++;
  624.         }
  625. }
  626.  
  627. void draw_explosion( struct explosion_t* e )
  628. {
  629.         div_t result;
  630.         float tex[8];// = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
  631.         float s, t;
  632.         float w = 320.0f, h = 320.0f;
  633.  
  634.         result = div( e->frame, 5 );
  635.         s = (float) result.rem * ( e->sx / w );
  636.         t = (float) 1.0f - ( result.quot * ( e->sy / h ) );
  637.  
  638.         tex[0] = s; tex[1] = t - e->sy / h;
  639.         tex[2] = s + e->sx / w; tex[3] = t - e->sy / h;
  640.         tex[4] = s + e->sx / w; tex[5] = t;
  641.         tex[6] = s; tex[7] = t;
  642.  
  643.         enable_2d();
  644.         push_pos();
  645.         transparent_blend( TRUE );
  646.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  647.         translate( e->x, e->y );
  648.         draw_quad2( get_texture( "expl2" ), tex, -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  649.         transparent_blend( FALSE );
  650.         pop_pos();
  651.         disable_2d();
  652. }
  653.  
  654. void draw_particle( const struct enemy_t* e )
  655. {
  656.         div_t result;
  657.         float tex[8];// = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
  658.         float s, t;
  659.  
  660.         result = div( e->frame, 5 );
  661.         s = (float) result.rem * ( e->sx / 160.0f );
  662.         t = (float) 1.0f - ( result.quot * ( e->sy / 192.0f ) );
  663.  
  664.         tex[0] = s; tex[1] = t + e->sy / 192.0f;
  665.         tex[2] = s + e->sx / 160.0f; tex[3] = t + e->sy / 192.0f;
  666.         tex[4] = s + e->sx / 160.0f; tex[5] = t;
  667.         tex[6] = s; tex[7] = t;
  668.  
  669.         enable_2d();
  670.         push_pos();
  671.         transparent_blend( TRUE );
  672.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  673.         translate( e->x, e->y );
  674.         draw_quad2( get_texture( "particle" ), tex, -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  675.         transparent_blend( FALSE );
  676.         pop_pos();
  677.         disable_2d();
  678. }
  679.  
  680. void draw_dragon( const struct enemy_t* e, int frame_offset )
  681. {
  682.         div_t result;
  683.         float tex[8];// = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
  684.         float s, t;
  685.         float w = 288.0f;
  686.         float h = 256.0f;
  687.  
  688.         result = div( e->frame + frame_offset, 5 );
  689.         s = (float) result.rem * ( e->sx / w );
  690.         t = (float) 1.0f - ( result.quot * ( e->sy / h ) );
  691.  
  692.         tex[0] = s; tex[1] = t + e->sy / h;
  693.         tex[2] = s + e->sx / w; tex[3] = t + e->sy / h;
  694.         tex[4] = s + e->sx / w; tex[5] = t;
  695.         tex[6] = s; tex[7] = t;
  696.  
  697.         enable_2d();
  698.         push_pos();
  699.         transparent_blend( TRUE );
  700.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  701.         translate( e->x, e->y );
  702.         draw_quad2( get_texture( "dragon2" ), tex, -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  703.         transparent_blend( FALSE );
  704.         pop_pos();
  705.         disable_2d();
  706. }
  707.  
  708. void draw_fairy( const struct enemy_t* e )
  709. {
  710.         /* Draw a simple fairy sprite */
  711.  
  712.         /* Enable 2D rendering */
  713.         enable_2d();
  714.  
  715.         /* Translate to the fairy's position */
  716.         push_pos();
  717.         translate( e->x, e->y );
  718.  
  719.         /* Alpha blending for colour key */
  720.         transparent_blend( TRUE );
  721.  
  722.         /* Set base colour to white */
  723.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  724.  
  725.         /* Draw the fairy sprite */
  726.         draw_quad( get_texture( "fairy" ), -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  727.  
  728.         /* Disable alpha blending */
  729.         transparent_blend( FALSE );
  730.  
  731.         /* Restore previous position */
  732.         pop_pos();
  733.  
  734.         /* Disable 2D rendering */
  735.         disable_2d();
  736. }
  737.  
  738. void draw_zeppelin( const struct enemy_t* e )
  739. {
  740.         float f = 0.0f;
  741.  
  742.         /* Draw a zeppelin sprite */
  743.  
  744.         /* Enable 2D rendering */
  745.         enable_2d();
  746.  
  747.         /* Translate to the fairy's position */
  748.         push_pos();
  749.         translate( e->x, e->y );
  750.  
  751.         /* Alpha blending for colour key */
  752.         transparent_blend( TRUE );
  753.  
  754.         /* Set base colour to white */
  755.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  756.  
  757.         /* Draw the fairy sprite */
  758.         draw_quad( get_texture( "zeppelin" ), -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  759.  
  760.         /* Disable alpha blending */
  761.         transparent_blend( FALSE );
  762.  
  763.         /* Let's draw an energy bar! */
  764.         if( !e->dying )
  765.         {
  766.                 set_colour( 1.0f, 0.0f, 0.0f, 1.0f );
  767.                 draw_line( -25.0f, -(e->sy/2.0f) - 10.0f, 25.0f, -(e->sy/2.0f) - 10.0f );
  768.                 f = (float) (((float)e->energy) / ((float)EMAX_ZEPPELIN) );
  769.                 set_colour( 0.0f, 1.0f, 0.0f, 1.0f );
  770.                 draw_line( -25.0f, -(e->sy/2.0f) - 10.0f, (f*50.0f)-25.0f, -(e->sy/2.0f) - 10.0f );
  771.         }
  772.  
  773.         /* Restore previous position */
  774.         pop_pos();
  775.  
  776.         /* Disable 2D rendering */
  777.         disable_2d();
  778. }
  779.  
  780. void draw_tank( const struct enemy_t* e )
  781. {
  782.         float f = 0.0f;
  783.  
  784.         /* Draw a tank sprite */
  785.  
  786.         /* Enable 2D rendering */
  787.         enable_2d();
  788.  
  789.         /* Translate to the tank's position */
  790.         push_pos();
  791.         translate( e->x, e->y );
  792.  
  793.         /* Rotate the tank as necessary */
  794.         push_pos();
  795.         rotate( e->rot );
  796.  
  797.         /* Alpha blending for colour key */
  798.         transparent_blend( TRUE );
  799.  
  800.         /* Set base colour to white */
  801.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  802.  
  803.         /* Draw the fairy sprite */
  804.         draw_quad( get_texture( "tank" ), -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  805.  
  806.         /* Disable alpha blending */
  807.         transparent_blend( FALSE );
  808.  
  809.         /* Undo rotation */
  810.         pop_pos();
  811.  
  812.         /* Let's draw an energy bar! */
  813.         if( !e->dying )
  814.         {
  815.                 set_colour( 1.0f, 0.0f, 0.0f, 1.0f );
  816.                 draw_line( -25.0f, -(e->sy/2.0f) - 10.0f, 25.0f, -(e->sy/2.0f) - 10.0f );
  817.                 f = (float) (((float)e->energy) / ((float)EMAX_TANK) );
  818.                 set_colour( 0.0f, 1.0f, 0.0f, 1.0f );
  819.                 draw_line( -25.0f, -(e->sy/2.0f) - 10.0f, (f*50.0f)-25.0f, -(e->sy/2.0f) - 10.0f );
  820.         }
  821.  
  822.         /* Restore previous position */
  823.         pop_pos();
  824.  
  825.         /* Disable 2D rendering */
  826.         disable_2d();
  827. }
  828.  
  829. void draw_drone( const struct enemy_t* e )
  830. {
  831.         /* Draw a simple drone sprite */
  832.  
  833.         /* Enable 2D rendering */
  834.         enable_2d();
  835.  
  836.         /* Translate to the drone's position */
  837.         push_pos();
  838.         translate( e->x, e->y );
  839.  
  840.         /* Alpha blending for colour key */
  841.         transparent_blend( TRUE );
  842.  
  843.         /* Set base colour to white */
  844.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  845.  
  846.         /* Draw the fairy sprite */
  847.         draw_quad( get_texture( "drone" ), -(e->sx/2.0f), -(e->sy/2.0f), e->sx, e->sy );
  848.  
  849.         /* Disable alpha blending */
  850.         transparent_blend( FALSE );
  851.  
  852.         /* Restore previous position */
  853.         pop_pos();
  854.  
  855.         /* Disable 2D rendering */
  856.         disable_2d();
  857. }
  858.  
  859. void move_dragon()
  860. {
  861.         if( move_up() )
  862.         {
  863.                 dragon.y -= 4.0f;
  864.         }
  865.         if( move_down() )
  866.         {
  867.                 dragon.y += 4.0f;
  868.         }
  869.         if( move_left() )
  870.         {
  871.                 dragon.x -= 4.0f;
  872.         }
  873.         if( move_right() )
  874.         {
  875.                 dragon.x += 4.0f;
  876.         }
  877.  
  878.         /* Boundary detection */
  879.         if( dragon.x < 160.0f )
  880.                 dragon.x = 160.0f;
  881.         if( dragon.x > 480.0f - dragon.width )
  882.                 dragon.x = 480.0f - dragon.width;
  883.         if( dragon.y < 0.0f )
  884.                 dragon.y = 0.0f;
  885.         if( dragon.y > 480.0f - dragon.height )
  886.                 dragon.y = 480.0f - dragon.height;
  887. }
  888.  
  889. void reset_and_activate_guard();
  890. int activate_overdrive();
  891. void turn_all_enemy_shoots_into_gold();
  892.  
  893. void check_for_special_input()
  894. {
  895.         if( special1_button() && dragon.powers[0] )
  896.         {
  897.                 turn_all_enemy_shoots_into_gold();
  898.                 dragon.powers[0] = No;
  899.         }
  900.  
  901.         if( special2_button() && dragon.powers[1] )
  902.         {
  903.                 if( activate_overdrive() )
  904.                         dragon.powers[1] = No;
  905.         }
  906.  
  907.         if( special3_button() && dragon.powers[2] )
  908.         {
  909.                 if( !guard.activated )
  910.                 {
  911.                         dragon.powers[2] = No;
  912.                         reset_and_activate_guard();
  913.                 }
  914.         }
  915. }
  916.  
  917. void ready_homing_blasts();
  918. void activate_fullautoblast( int id );
  919.  
  920. void handle_mouse_input()
  921. {
  922.         static int lb_down = 0;
  923.         static int rb_down = 0;
  924.         static int delay = 0;
  925.  
  926.         /* Process left mouse clicks */
  927.         if( shoot_button_down() )
  928.         {
  929.                 /* Signify that the left mouse button is down */
  930.                 lb_down = 1;
  931.  
  932.                 /* What firing mode are we using? */
  933.                 if( dragon.attack_mode == 0 )
  934.                 {
  935.                         /* Full auto plays the rapid fire sound effect */
  936.                         if( ++delay == 3 )
  937.                         {
  938.                                 int fa_id = 0;
  939.                                
  940.                                 play_sound_effect_static( &sfx[10], 0 );
  941.  
  942.                                 fa_id = find_inactive_fullautoblast();
  943.                                 if( fa_id != -1 )
  944.                                 {
  945.                                         activate_fullautoblast( fa_id );
  946.                                 }
  947.                                 delay = 0;
  948.                         }
  949.                 }
  950.                 else
  951.                 {
  952.                         /* Lock mode plays the lock sound effect when new locks are aquired
  953.                            (not in this function) and the homing blast sound effect when the
  954.                            button is released */
  955.                 }
  956.         }
  957.         else
  958.         {
  959.                 /* Was the left mouse button just released? */
  960.                 if( lb_down == 1 )
  961.                 {
  962.                         lb_down = 0;
  963.  
  964.                         /* Play the homing blast sound effect if there are any locks */
  965.                         /* Also reset any locks */
  966.                         if( active_locks_available() && active_homing_blasts() == 0 )
  967.                         {
  968.                                 play_sound_effect( &sfx[2], 0 );
  969.                                 ready_homing_blasts();
  970.                                 reset_all_locks( TRUE );
  971.                         }
  972.                 }
  973.         }
  974. }
  975.  
  976. void draw_enemies()
  977. {
  978. #if 0
  979.         struct enemy_t e;
  980.         static frame = 0;
  981.  
  982.         e.dead = 0;
  983.         e.frame = frame;
  984.         e.lock = 0;
  985.         e.sx = 32.0f;
  986.         e.sy = 32.0f;
  987.         e.type = ENEMY_PARTICLE;
  988.         e.x = 160.0f;
  989.         e.y = 50.0f;
  990.  
  991.         draw_particle( &e );
  992.         if( ++frame > 29 )
  993.                 frame = 0;
  994. #else
  995.         int i = 0;
  996.  
  997.         /* Go through list of enemies */
  998.         while( i < MAX_ENEMIES )
  999.         {
  1000.                 /* Is this enemy active/alive? */
  1001.                 if( !enemies[i].dead )
  1002.                 {
  1003.                         /* If so, render it */
  1004.                        
  1005.                         /* Flash if flashing */
  1006.                         if( enemies[i].flash ) flash_white( Yes );
  1007.  
  1008.                         switch( enemies[i].type )
  1009.                         {
  1010.                         case ENEMY_PARTICLE:    draw_particle( &enemies[i] ); break;
  1011.                         case ENEMY_REDDRAGON:   draw_dragon( &enemies[i], 10 ); break;
  1012.                         case ENEMY_GREENDRAGON: draw_dragon( &enemies[i], 0 ); break;
  1013.                         case ENEMY_BLUEDRAGON:  draw_dragon( &enemies[i], 15 ); break;
  1014.                         case ENEMY_BLACKDRAGON: draw_dragon( &enemies[i], 5 ); break;
  1015.                         case ENEMY_FAIRY:               draw_fairy( &enemies[i] ); break;
  1016.                         case ENEMY_ZEPPELIN:    draw_zeppelin( &enemies[i] ); break;
  1017.                         case ENEMY_TANK:                draw_tank( &enemies[i] ); break;
  1018.                         case ENEMY_DRONE:               draw_drone( &enemies[i] ); break;
  1019.                         default: break;
  1020.                         }
  1021.                        
  1022.                         /* Stop flashing */
  1023.                         if( enemies[i].flash ) flash_white( No );
  1024.  
  1025.                         /* Stop flashing */
  1026.                         enemies[i].flash = No;
  1027.  
  1028.                         /* Update the sprite's key frame animation */
  1029.                         if( enemies[i].timer++ >= enemies[i].max_timer )
  1030.                         {
  1031.                                 enemies[i].timer = 0;
  1032.  
  1033.                                 if( ++enemies[i].frame >= enemies[i].max_frame )
  1034.                                         enemies[i].frame = 0;
  1035.                         }
  1036.  
  1037.                         /* Move this enemy according to it's movement pattern */
  1038.                         if( enemies[i].movement == EMOVEMENT_SPLINE )
  1039.                         {
  1040.                                 /* TODO: Move enemy along it's spline. */
  1041.                                 /* TODO: When enemy moves offscreen to it's final destination.
  1042.                                                  mark it as dead, but obviously give no score for it either */
  1043.                                 if( move_position_on_spline( &spline ) )
  1044.                                         enemies[i].dead = Yes;
  1045.                                 else
  1046.                                 {
  1047.                                         struct Vector2 v;
  1048.                                         get_current_position_on_spline( &spline, &v );
  1049.  
  1050.                                         enemies[i].x = v.x;
  1051.                                         enemies[i].y = v.y;
  1052.                                 }
  1053.                         }
  1054.                         else if( enemies[i].movement == EMOVEMENT_STILL )
  1055.                         {
  1056.                                 /* Move the enemy with the screen */
  1057.                                 enemies[i].y += scroll_speed;
  1058.  
  1059.                                 /* When the enemy has gone below the screen, mark it as inactive */
  1060.                                 if( enemies[i].y > 480.0f )
  1061.                                         enemies[i].dead = Yes;
  1062.                         }
  1063.  
  1064.                         /* Check for dying enemies */
  1065.                         if( enemies[i].dying && !enemies[i].dead )
  1066.                         {
  1067.                                 /* Dying enemies (such as zeppelins) need special attention */
  1068.                                 if( enemies[i].type == ENEMY_ZEPPELIN )
  1069.                                 {
  1070.                                         static int interval = 0;
  1071.  
  1072.                                         /* Decrease ship size to make it look like it's falling */
  1073.                                         enemies[i].sx -= 1.0f;
  1074.                                         enemies[i].sy -= 1.0f;
  1075.                                         enemies[i].y += 0.5f;
  1076.  
  1077.                                         /* Add a new smoke puff every 10 frames */
  1078.                                         if( interval <= 0 )
  1079.                                         {
  1080.                                                 add_smoke_puff( enemies[i].x, enemies[i].y, SMOKEANIM_RISE );
  1081.                                                 interval = 10;
  1082.                                         }
  1083.                                         else
  1084.                                                 interval--;
  1085.  
  1086.  
  1087.                                         /* Is the zeppelin small enough now? */
  1088.                                         if( enemies[i].sx < ( 76.0f/3.0f ) && enemies[i].sy < ( 100.0f/3.0f ) )
  1089.                                         {
  1090.                                                 enemies[i].dead = Yes;
  1091.                                                 kill_enemy( &enemies[i], 9 );
  1092.                                         }
  1093.                                 }
  1094.                         }
  1095.  
  1096.                         /* Enemy specific updates */
  1097.                         if( enemies[i].type == ENEMY_DRONE )
  1098.                                 update_drone( &enemies[i] );
  1099.                 }
  1100.  
  1101.                 i++;
  1102.         }
  1103. #endif
  1104. }
  1105.  
  1106. void reset_and_activate_guard()
  1107. {
  1108.         /* Reset and activate the guard ability */
  1109.  
  1110.         guard.activated = Yes;
  1111.         guard.angle = 0.0f;
  1112.         guard.dist = 1.0f;
  1113.         guard.expired = No;
  1114.         guard.timer = 1000;
  1115. }
  1116.  
  1117. void draw_guard_if_activated()
  1118. {
  1119.         int i = 0;
  1120.         float size = 24.0f;
  1121.  
  1122.         if( !guard.activated )
  1123.                 return 0;
  1124.  
  1125.         /* Draw guard crystals */
  1126.  
  1127.         enable_2d();
  1128.         transparent_blend( Yes );
  1129.  
  1130.         while( i < 3 )
  1131.         {
  1132.                 push_pos();
  1133.                 translate( guard.x[i], guard.y[i] );
  1134.                 draw_quad( get_texture( "guard" ), -(size/2.0f), -(size/2.0f), size, size );
  1135.                 pop_pos();
  1136.  
  1137.                 i++;
  1138.         }
  1139.  
  1140.         transparent_blend( No );
  1141.         disable_2d();
  1142. }
  1143.  
  1144.  
  1145. void update_guard_if_activated()
  1146. {
  1147.         int i = 0;
  1148.  
  1149.         if( !guard.activated )
  1150.                 return 0;
  1151.  
  1152.         /* Update the angle that the guard crystal is rotating */
  1153.         guard.angle += 0.1f;
  1154.  
  1155.         /* Move further outward if the maximum distance was not reached */
  1156.         if( guard.dist < 70.0f && !guard.expired )
  1157.                 guard.dist++;
  1158.  
  1159.         /* Move inward if the guard is expiring */
  1160.         if( guard.expired && guard.dist > 0.0f )
  1161.                 guard.dist--;
  1162.  
  1163.         /* Deactivate the guard if finished */
  1164.         if( guard.expired && guard.dist <= 0.0f )
  1165.                 guard.activated = No;
  1166.  
  1167.         /* Set the position of all 3 guard crystals */
  1168.         while( i < 3 )
  1169.         {
  1170.                 guard.x[i] = guard.dist * cos( ( i * 2.0f * 3.14f / 3.0f ) + guard.angle ) + ( dragon.x + ( dragon.width / 2.0f ) );
  1171.                 guard.y[i] = guard.dist * sin( ( i * 2.0f * 3.14f / 3.0f ) + guard.angle ) + ( dragon.y + ( dragon.height / 2.0f ) );
  1172.                 i++;
  1173.         }
  1174.  
  1175.         /* Update expiration timer */
  1176.         if( --guard.timer <= 0 )
  1177.                 guard.expired = Yes;
  1178.  
  1179.         i = 0;
  1180.  
  1181.         /* Check each guard crystal for a collision */
  1182.         while( i < 3 )
  1183.         {
  1184.                 int j = 0;
  1185.  
  1186.                 /* Check each enemy for a collision test */
  1187.                 while( j < MAX_ENEMIES )
  1188.                 {
  1189.                         /* Is this enemy alive so we can kill it? */
  1190.                         if( !enemies[j].dead )
  1191.                         {
  1192.                                 /* It is, let's check to see if the guard crystal did it's job */
  1193.                                 if( guard.x[i] >= enemies[j].x && guard.x[i] <= enemies[j].x+enemies[j].sx &&
  1194.                                         guard.y[i] >= enemies[j].y && guard.y[i] <= enemies[j].y+enemies[j].sy )
  1195.                                 {
  1196.                                         /* Do 5 damage */
  1197.                                         enemies[j].energy -= 25;
  1198.  
  1199.                                         /* Is this enemy dead? */
  1200.                                         if( enemies[j].energy <= 0 )
  1201.                                         {
  1202.                                                 /* Enemy zeppelin's don't die automatically */
  1203.                                                 if( enemies[j].type == ENEMY_ZEPPELIN )
  1204.                                                         enemies[j].dying = Yes;
  1205.                                                 else
  1206.                                                 {
  1207.                                                         /* Katsu! */
  1208.                                                         kill_enemy( &enemies[j], 7 );
  1209.                                                 }
  1210.                                         }
  1211.                                         else
  1212.                                         {
  1213.                                                 /* If not, just flash white for a frame */
  1214.                                                 enemies[j].flash = Yes;
  1215.                                         }
  1216.                                        
  1217.                                         /* Let homing blast go */
  1218.                                 //      homingblasts[i].target = -1;
  1219.                                 //      homingblasts[i].fade_timer = 200;
  1220.                                 }
  1221.                         }
  1222.  
  1223.                         j++;
  1224.                 }
  1225.  
  1226.                 i++;
  1227.         }
  1228. }
  1229.  
  1230. int activate_overdrive()
  1231. {
  1232.         /* Activates overdrive! */
  1233.  
  1234.         /* Don't activate overdrive if the timer from the previous session
  1235.            has not expired. If it hasn't return 0 so that the power up is
  1236.            not marked as used until this session is over! */
  1237.  
  1238.         if( overdrive_timer > 0 )
  1239.                 return 0;
  1240.  
  1241.         overdrive_timer = 500;
  1242. }
  1243.  
  1244. void update_overdrive_if_active()
  1245. {
  1246.         /* If the overdrive power up is active, decrease the timer */
  1247.         if( overdrive_timer > 0 )
  1248.                 overdrive_timer--;
  1249. }
  1250.  
  1251. void reset_powerups()
  1252. {
  1253.         memset( powerups, 0, sizeof( struct powerup_t ) * 4 );
  1254. }
  1255.  
  1256. void give_possible_powerup( float x, float y )
  1257. {
  1258.         /* This function should be called every time an applicable targetable enemy is
  1259.            destroyed. It randomly decides wither the player gets a power up to recieve.
  1260.            There is a 1 in 20 chance of getting a power up, but the odds for getting
  1261.            certain ones can vary.  The odds table contains a list of powerups.  The less
  1262.            frequent the powerup is on the table, the less likely you are to get that one.
  1263.            Heart #2 is designed to the the rarest. */
  1264.        
  1265.         int i = 0;
  1266.         int odds[10] = { 1, 1, 1, 2, 2, 3, 3, 4, 4, 5 };
  1267.  
  1268.         /* Check odds of actually getting anything.... */
  1269.         if( (rand()%5) != 1 )
  1270.                 return;         /* *BUZZER!* Not this time. */
  1271.  
  1272.         /* *DING DING DING!* We have a winner! */
  1273.         while( i < 4 )
  1274.         {
  1275.                 /* Search the list for an inactive powerup.  If we find one, activate it */
  1276.                 if( !powerups[i].active )
  1277.                 {
  1278.                         powerups[i].active = Yes;
  1279.                         powerups[i].x = x;
  1280.                         powerups[i].y = y;
  1281.                         powerups[i].type = odds[(rand()%10)];
  1282.                         powerups[i].vx = 3.0f;
  1283.                         powerups[i].vy = 3.0f;
  1284.                         powerups[i].sx = powerups[i].sy = 32.0f;
  1285.  
  1286.                         return;
  1287.                 }
  1288.  
  1289.                 i++;
  1290.         }
  1291. }
  1292.  
  1293. void draw_powerups()
  1294. {
  1295.         int i = 0;
  1296.         char string[16];
  1297.  
  1298.         enable_2d();
  1299.         transparent_blend( Yes );
  1300.  
  1301.         /* Render each power up */
  1302.         while( i < 4 )
  1303.         {
  1304.                 /* Is it active? */
  1305.                 if( powerups[i].active )
  1306.                 {
  1307.                         /* get the actual texture name */
  1308.                         switch( powerups[i].type )
  1309.                         {
  1310.                         case POWER_CRYSTAL1:
  1311.                                 sprintf( string, "diamond1.tga" );
  1312.                                 break;
  1313.                         case POWER_CRYSTAL2:
  1314.                                 sprintf( string, "diamond2.tga" );
  1315.                                 break;
  1316.                         case POWER_CRYSTAL3:
  1317.                                 sprintf( string, "diamond3.tga" );
  1318.                                 break;
  1319.                         case POWER_HEART1:
  1320.                                 sprintf( string, "heart1.tga" );
  1321.                                 break;
  1322.                         case POWER_HEART2:
  1323.                                 sprintf( string, "heart2.tga" );
  1324.                                 break;
  1325.                         }                      
  1326.  
  1327.                         /* Now actually render the powerup sprite */
  1328.                         push_pos();
  1329.                         translate( powerups[i].x, powerups[i].y );
  1330.                         draw_quad( get_texture( string ), -16.0f, -16.0f, 32.0f, 32.0f );
  1331.                         pop_pos();
  1332.                 }
  1333.  
  1334.                 i++;
  1335.         }
  1336.        
  1337.         transparent_blend( Yes );
  1338.         disable_2d();
  1339. }
  1340.  
  1341. void update_powerups()
  1342. {
  1343.         int i = 0;
  1344.  
  1345.         /* Update each active powerup */
  1346.         while( i < 4 )
  1347.         {
  1348.                 /* Only if it's active... */
  1349.                 if( powerups[i].active )
  1350.                 {
  1351.                         /* Move the powerup icon around */
  1352.                         powerups[i].x += powerups[i].vx;
  1353.                         powerups[i].y += powerups[i].vy;
  1354.  
  1355.                         /* Check boundaries */
  1356.                         if( powerups[i].x <= 160.0f )
  1357.                                 powerups[i].vx *= -1.0f;
  1358.                         if( powerups[i].x >= 480.0f )
  1359.                                 powerups[i].vx *= -1.0f;
  1360.  
  1361.                         if( powerups[i].y <= 0.0f || powerups[i].y >= 480.0f )
  1362.                                 powerups[i].vy *= -1.0f;
  1363.  
  1364.                         /* Check for collision with player */
  1365.                         if( powerups[i].x >= dragon.x && powerups[i].x <= dragon.x + dragon.width &&
  1366.                                 powerups[i].y >= dragon.y && powerups[i].y <= dragon.y + dragon.height )
  1367.                         {
  1368.                                 /* Deactivate powerup */
  1369.                                 powerups[i].active = No;
  1370.  
  1371.                                 /* Play the confirmation sound */
  1372.                                 play_sound_effect_static( &sfx[0], 0 );
  1373.  
  1374.                                 /* Get the actual texture name */
  1375.                                 switch( powerups[i].type )
  1376.                                 {
  1377.                                 case POWER_CRYSTAL1:
  1378.                                         dragon.powers[0] = Yes;
  1379.                                         break;
  1380.                                 case POWER_CRYSTAL2:
  1381.                                         dragon.powers[1] = Yes;
  1382.                                         break;
  1383.                                 case POWER_CRYSTAL3:
  1384.                                         dragon.powers[2] = Yes;
  1385.                                         break;
  1386.                                 case POWER_HEART1:
  1387.                                         dragon.energy += 25;
  1388.                                         if( dragon.energy > dragon.max_energy )
  1389.                                                 dragon.energy = dragon.max_energy;
  1390.                                         break;
  1391.                                 case POWER_HEART2:
  1392.                                         dragon.max_energy += 25;
  1393.                                         dragon.energy += 25;
  1394.                                         break;
  1395.                                 }      
  1396.                         }
  1397.                 }
  1398.  
  1399.                 i++;
  1400.         }
  1401. }
  1402.  
  1403. void reset_enemy_shoots()
  1404. {
  1405.         memset( enemyshoots, 0, sizeof( struct enemyshoot_t ) * MAX_ENEMYSHOOTS );
  1406. }
  1407.  
  1408. int find_inactive_enemy_shoots()
  1409. {
  1410.         int i = 0;
  1411.  
  1412.         /* Traverse through the list of enemy shoots and find the first inactive shoot */
  1413.         while( i < MAX_ENEMYSHOOTS )
  1414.         {
  1415.                 if( !enemyshoots[i].active )
  1416.                         return i;
  1417.  
  1418.                 i++;
  1419.         }
  1420.  
  1421.         return -1;
  1422. }
  1423.  
  1424. void add_new_enemy_shoot( float x, float y, float speed, int type )
  1425. {
  1426.         /* Activate a new enemy shoot. If none are free, abort */
  1427.         /* TODO: Respond to above issue if we run out of shoots to make more space later */
  1428.  
  1429.         int shoot = find_inactive_enemy_shoots();
  1430.  
  1431.         /* Verify we have any inactive shoots */
  1432.         if( shoot == -1 )
  1433.                 return;
  1434.  
  1435.         /* Update the number of active shoots */
  1436.         active_shoots++;
  1437.  
  1438.         /* Activate this shoot */
  1439.         enemyshoots[shoot].active = Yes;
  1440.         enemyshoots[shoot].x = x;
  1441.         enemyshoots[shoot].y = y;
  1442.         enemyshoots[shoot].angle = angle( x, y, dragon.x+(dragon.width/2.0f), dragon.y+(dragon.height/2.0f) );
  1443.         enemyshoots[shoot].dx = cos( enemyshoots[shoot].angle );
  1444.         enemyshoots[shoot].dy = sin( enemyshoots[shoot].angle );
  1445.         enemyshoots[shoot].speed = speed;
  1446.         enemyshoots[shoot].type = type;
  1447.  
  1448.         /*fullautoblasts[id].active = Yes;
  1449.         fullautoblasts[id].x = dragon.x + (dragon.width/2.0f);
  1450.         fullautoblasts[id].y = dragon.y + (dragon.height/2.0f);
  1451.         fullautoblasts[id].size = ( overdrive_timer > 0 ) ? 64.0f : 32.0f;
  1452.  
  1453.         fullautoblasts[id].angle = angle( dragon.x+(dragon.width/2.0f), dragon.y+(dragon.height/2.0f),
  1454.                 ch.x, ch.y );
  1455.         fullautoblasts[id].dirx = cos( fullautoblasts[id].angle );
  1456.         fullautoblasts[id].diry = sin( fullautoblasts[id].angle );
  1457.         fullautoblasts[id].speed = 15.0f;*/
  1458.  
  1459.         /* TODO: Handle animations, etc */
  1460.         /* TODO: Different shot types */
  1461.         switch( type )
  1462.         {
  1463.         case 0: /* Standard */
  1464.                 enemyshoots[shoot].damage = 15;
  1465.                 enemyshoots[shoot].frame = 0;
  1466.                 enemyshoots[shoot].max_frame = 0;
  1467.                 enemyshoots[shoot].sx = 12.0f;
  1468.                 enemyshoots[shoot].sy = 22.0f;
  1469.                 break;
  1470.  
  1471.         case 1: /* Cannon ball */
  1472.                 enemyshoots[shoot].damage = 30;
  1473.                 break;
  1474.         }
  1475. }
  1476.  
  1477. void draw_enemy_shoots()
  1478. {
  1479.         int i = 0;
  1480.  
  1481.         /* Draw each enemy shoot */
  1482.  
  1483.         enable_2d();
  1484.         transparent_blend( Yes );
  1485.  
  1486.         while( i < MAX_ENEMYSHOOTS )
  1487.         {
  1488.                 /* Is this shoot active? */
  1489.                 if( enemyshoots[i].active )
  1490.                 {
  1491.                         push_pos();
  1492.                         translate( enemyshoots[i].x, enemyshoots[i].y );
  1493.                         rotate( enemyshoots[i].angle*(180.0f/3.14f)+90.0f );
  1494.                         draw_quad( get_texture( "shot1" ),
  1495.                                 -(enemyshoots[i].sx/2.0f),
  1496.                                 -(enemyshoots[i].sy/2.0f),
  1497.                                 enemyshoots[i].sx, enemyshoots[i].sy );
  1498.                         pop_pos();
  1499.                 }
  1500.  
  1501.                 i++;
  1502.         }
  1503.  
  1504.         transparent_blend( No );
  1505.         disable_2d();
  1506. }
  1507.  
  1508. void update_enemy_shoots()
  1509. {
  1510.         int i = 0;
  1511.  
  1512.         /* Update each enemy shoot */
  1513.         while( i < MAX_ENEMYSHOOTS )
  1514.         {
  1515.                 if( enemyshoots[i].active )
  1516.                 {
  1517.                         float x1 = (dragon.x+(dragon.width/2.0f)-4.0f);
  1518.                         float x2 = (dragon.x+(dragon.width/2.0f)+4.0f);
  1519.                         float y1 = (dragon.y+(dragon.height/2.0f)-4.0f);
  1520.                         float y2 = (dragon.y+(dragon.height/2.0f)+4.0f);
  1521.  
  1522.                         /* Move each shoot in it's designated direction */
  1523.                         enemyshoots[i].x += enemyshoots[i].dx * enemyshoots[i].speed;
  1524.                         enemyshoots[i].y += enemyshoots[i].dy * enemyshoots[i].speed;
  1525.  
  1526.                         /* Deactivate any shoots that go out of the boundaries */
  1527.                         if( enemyshoots[i].x < 160.0f || enemyshoots[i].x > 480.0f ||
  1528.                                 enemyshoots[i].y < 0.0f || enemyshoots[i].y > 480.0f )
  1529.                         {
  1530.                                 enemyshoots[i].active = No;
  1531.                                 active_shoots--;
  1532.                         }
  1533.  
  1534.                         /* Check for collisions with player dragon */
  1535.                         if( enemyshoots[i].x > x1 && enemyshoots[i].x < x2 &&
  1536.                                 enemyshoots[i].y > y1 && enemyshoots[i].y < y2 )
  1537.                         {
  1538.                                 /* Oh no, we've been hit! */
  1539.  
  1540.                                 /* Don't do damage if we are flashing */
  1541.                                 if( dragon.inv_t == 0 )
  1542.                                 {
  1543.                                         dragon.energy -= enemyshoots[i].damage;
  1544.                                         dragon.inv_t = 100;
  1545.                                 }                              
  1546.  
  1547.                                 if( dragon.energy < 0 )
  1548.                                         dragon.energy = 0;
  1549.  
  1550.                                 enemyshoots[i].active = No;
  1551.                                 active_shoots--;
  1552.                         }
  1553.  
  1554.                         /* Check for collisions with guard crystals if active */
  1555.                         if( guard.activated && enemyshoots[i].active )
  1556.                         {
  1557.                                 /* TODO: FIXME!!! */
  1558.                                 int j = 0;
  1559.                                
  1560.                                 while( j < 3 )
  1561.                                 {
  1562.                                         float gx1 = (guard.x[i]-12.0f);
  1563.                                         float gy1 = (guard.y[i]-12.0f);
  1564.                                         float gx2 = (guard.x[i]+12.0f);
  1565.                                         float gy2 = (guard.y[i]+12.0f);
  1566.  
  1567.                                         /*enable_2d();
  1568.                                         wireframe(Yes);
  1569.                                         draw_quad( 0, gx1, gy1, 24, 24 );
  1570.                                         wireframe(No);
  1571.                                         disable_2d();*/
  1572.  
  1573.                                         /* Did it collide? */
  1574.                                         if( enemyshoots[i].x > gx1 && enemyshoots[i].x < gx2 &&
  1575.                                                 enemyshoots[i].y > gy1 && enemyshoots[i].y < gy2 )
  1576.                                         {
  1577.                                                 /* If so, deactivate shot */
  1578.                                                 enemyshoots[i].active = No;
  1579.                                                 active_shoots--;
  1580.                                                 break;
  1581.                                         }
  1582.  
  1583.                                         j++;
  1584.                                 }
  1585.                         }
  1586.                 }
  1587.  
  1588.                 i++;
  1589.         }
  1590. }
  1591.  
  1592. void check_enemy_shoots_for_collisions()
  1593. {
  1594.         /* TODO */
  1595. }
  1596.  
  1597. void turn_all_enemy_shoots_into_gold()
  1598. {
  1599.         /* Turn all active enemy shoots into gold peices */
  1600.  
  1601.         int i = 0;
  1602.  
  1603.         while( i < MAX_ENEMYSHOOTS )
  1604.         {
  1605.                 if( enemyshoots[i].active )
  1606.                 {
  1607.                         enemyshoots[i].active = No;
  1608.                         active_shoots--;
  1609.  
  1610.                         add_gold_peice( enemyshoots[i].x, enemyshoots[i].y );
  1611.                 }
  1612.  
  1613.                 i++;
  1614.         }
  1615. }
  1616.  
  1617. void init_boss( int level )
  1618. {
  1619.         /* Setup the boss structure depending on what boss we are facing */
  1620.         memset( &boss, 0, sizeof( struct boss_t ) );
  1621.  
  1622.         /* Mask */
  1623.         if( level == 1 )
  1624.         {
  1625.                 boss.x = 320.0f /*- (365.0f/2.0f)*/;
  1626.                 boss.y = 150.0f;
  1627.                 boss.sx = 365.0f;
  1628.                 boss.sy = 285.0f;
  1629.                 boss.max_energy = 1000.0f;
  1630.                 boss.energy = 900.0f;
  1631.                 boss.type = BOSS_MASK;
  1632.                 boss.lock_points = 8;
  1633.         }
  1634.  
  1635.         boss_mode = Yes;
  1636. }
  1637.  
  1638. void draw_boss()
  1639. {
  1640.         float f = 0.0f;
  1641.  
  1642.         if( boss_mode )
  1643.         {
  1644.                 enable_2d();
  1645.                 transparent_blend(Yes);
  1646.                 push_pos();
  1647.                 translate( boss.x, boss.y );
  1648.                 draw_quad( get_texture( "boss1" ), -boss.sx/2.0f, -boss.sy/2.0f, boss.sx, boss.sy );
  1649.                 pop_pos();
  1650.  
  1651.                 f = (boss.energy/boss.max_energy) * 300.0f;
  1652.  
  1653.                 set_colour( 1.0f, 0.0f, 0.0f, 0.5f );
  1654.                 translate( 160.0f, 20.0f );
  1655.                 draw_quad( 0, 10.0f, 0, f, 8.0f );
  1656.                 set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  1657.                 draw_line( 10.0f, 0.0f, 310.0f, 0.0f );
  1658.                 draw_line( 10.0f, 8.0f, 310.0f, 8.0f );
  1659.                 draw_line( 10.0f, 0.0f, 10.0f, 8.0f );
  1660.                 draw_line( 310.0f, 0.0f, 310.0f, 8.0f );
  1661.  
  1662.                 transparent_blend(No);
  1663.                 disable_2d();
  1664.         }
  1665. }
  1666.  
  1667. void update_boss()
  1668. {
  1669. }
  1670.  
  1671. int init_textures()
  1672. {
  1673.         HFASTFILE               ff;
  1674.         struct _iobuf*  fp;
  1675.         struct _iobuf*  out;
  1676.         void*                   buffer;
  1677.         int                             i = 0;
  1678.         int                             failed = 0;
  1679.  
  1680.         /* Try to open data00.dat */
  1681.         out = fopen( "data00.dat", "r" );
  1682.  
  1683.         /* If it's there, read the fastfile attributes from there. */
  1684.         /* If not, then either create it ourselves or just fail (release builds) */
  1685.         if( !out )
  1686.         {
  1687.                 /* Create a data file to contain the sizes of each texture */
  1688.                 out = fopen( "data00.dat", "w" );
  1689.                 fprintf( out, "files: %d\n\n", MAX_TEXTURES );
  1690.  
  1691.                 /* Retrieve the file size of each texture (TEMPORARY) */
  1692.                 while( i < MAX_TEXTURES )
  1693.                 {
  1694.                         char filename[128];
  1695.  
  1696.                         sprintf( filename, "..\\Media\\textures\\%s", tex_files[i] );
  1697.                         fp = fopen( filename, "rb" );
  1698.                         if( !fp )
  1699.                         {
  1700.                                 MessageBox( NULL, filename, "Pale Dragon", MB_OK );
  1701.                                 return 0;
  1702.                         }
  1703.  
  1704.                         fseek( fp, 0, SEEK_END );
  1705.                         tex_file_sizes[i] = ftell( fp );
  1706.  
  1707.                         if( out )
  1708.                                 fprintf( out, "%d\n", tex_file_sizes[i] );
  1709.  
  1710.                         fclose(fp);
  1711.  
  1712.                         i++;
  1713.                 }
  1714.         }
  1715.         else
  1716.         {
  1717.                 int files = 0;
  1718.  
  1719.                 /* Get the number of files within this fastfile */
  1720.                 fscanf( out, "files: %d\n\n", &files );
  1721.  
  1722.                 /* Get the sizes of each file within this fastfile */
  1723.                 while( i < files )
  1724.                 {
  1725.                         fscanf( out, "%d\n", &tex_file_sizes[i] );
  1726.                         i++;
  1727.                 }
  1728.         }
  1729.  
  1730.         /* Close the data file */
  1731.         if( out )
  1732.                 fclose( out );
  1733.  
  1734.         /* Initialize the fastfile */
  1735.         if( !FastFileInit( "data00.bin", MAX_TEXTURES ) )
  1736.                 return 0;
  1737.  
  1738.         /* Start loading files from the fast file */
  1739.         i = 0;
  1740.         while( i < MAX_TEXTURES )
  1741.         {
  1742.                 /* Get a handle to the file */
  1743.                 ff = FastFileOpen( tex_files[i] );
  1744.                 if(ff)
  1745.                 {
  1746.                         /* If we find the file, allocate a buffer large enough so it can
  1747.                            be read as a file in memory */
  1748.                         buffer = malloc( tex_file_sizes[i] );
  1749.  
  1750.                         /* Now actually read in the file's data */
  1751.                         FastFileRead( ff, buffer, tex_file_sizes[i] );
  1752.  
  1753.                         /* Now that we have a valid file pointer with data, create a
  1754.                            texture from it */
  1755.                         textures[i] = create_texture_from_file( buffer, tex_files[i] );
  1756.  
  1757.                         /* Free the buffer */
  1758.                         free( buffer );
  1759.  
  1760.                         /* Close the fastfile handle */
  1761.                         FastFileClose( ff );
  1762.                 }
  1763.                 else
  1764.                 {
  1765.                         failed++;
  1766.                 }
  1767.  
  1768.                 i++;
  1769.         }
  1770.  
  1771.         /* Uninitialize the fast file */
  1772.         FastFileFini();
  1773.  
  1774.         /* Show any failed texture loads */
  1775.         if( failed )
  1776.         {
  1777.                 char string[64];
  1778.  
  1779.                 sprintf( string, "%d out of %d failed texture loads!", failed, MAX_TEXTURES );
  1780.                 MessageBox( NULL, string, "Pale Dragon", MB_OK );
  1781.         }
  1782.  
  1783. #if 0
  1784.         /* TODO: Load textures from fastfile resource */
  1785.         if( !( textures[TEX_CROSSHAIR1] = create_texture( "..\\Media\\textures\\crosshair1.tga" ) ) ) return 0;
  1786.         if( !( textures[TEX_CROSSHAIR2] = create_texture( "..\\Media\\textures\\crosshair2.tga" ) ) ) return 0;
  1787.         if( !( textures[TEX_DRAGON1]    = create_texture( "..\\Media\\textures\\dragon1.tga" ) ) ) return 0;
  1788.         if( !( textures[TEX_DRAGON2]    = create_texture( "..\\Media\\textures\\dragon2.tga" ) ) ) return 0;
  1789.         if( !( textures[TEX_HEALTH]             = create_texture( "..\\Media\\textures\\heart.tga" ) ) ) return 0;
  1790.         if( !( textures[TEX_POWERUP1]   = create_texture( "..\\Media\\textures\\diamond1.tga" ) ) ) return 0;
  1791.         if( !( textures[TEX_POWERUP2]   = create_texture( "..\\Media\\textures\\diamond2.tga" ) ) ) return 0;
  1792.         if( !( textures[TEX_POWERUP3]   = create_texture( "..\\Media\\textures\\diamond3.tga" ) ) ) return 0;
  1793.         if( !( textures[TEX_BACKGROUND] = create_texture( "..\\Media\\textures\\bkg1.tga" ) ) ) return 0;
  1794.         if( !( textures[TEX_HOMINGSHOT] = create_texture( "..\\Media\\textures\\hblast.tga" ) ) ) return 0;
  1795.         if( !( textures[TEX_SHOT]               = create_texture( "..\\Media\\textures\\shot.tga" ) ) ) return 0;
  1796.         if( !( textures[TEX_REDSHOT]    = create_texture( "..\\Media\\textures\\fbred.tga" ) ) ) return 0;
  1797.         if( !( textures[TEX_GREENSHOT]  = create_texture( "..\\Media\\textures\\fbgreen.tga" ) ) ) return 0;
  1798.         if( !( textures[TEX_PARTICLE]   = create_texture( "..\\Media\\textures\\particle.tga" ) ) ) return 0;
  1799.         if( !( textures[TEX_EXPLOSION]  = create_texture( "..\\Media\\textures\\explosion.tga" ) ) ) return 0;
  1800.         if( !( textures[TEX_DIRT]       = create_texture( "..\\Media\\textures\\dirt.tga" ) ) ) return 0;
  1801.         if( !( textures[TEX_SAND]       = create_texture( "..\\Media\\textures\\sand.tga" ) ) ) return 0;
  1802.         if( !( textures[TEX_GRASS]      = create_texture( "..\\Media\\textures\\grass.tga" ) ) ) return 0;
  1803.         if( !( textures[TEX_WATER]      = create_texture( "..\\Media\\textures\\water.tga" ) ) ) return 0;
  1804.         if( !( textures[TEX_INDOOR1]    = create_texture( "..\\Media\\textures\\intile1.tga" ) ) ) return 0;
  1805.         if( !( textures[TEX_INDOOR2]    = create_texture( "..\\Media\\textures\\intile2.tga" ) ) ) return 0;
  1806.         if( !( textures[TEX_INDOOR2D]   = create_texture( "..\\Media\\textures\\intile2d.tga" ) ) ) return 0;
  1807.         if( !( textures[TEX_INDOOR3]    = create_texture( "..\\Media\\textures\\intile3.tga" ) ) ) return 0;
  1808.         if( !( textures[TEX_INDOOR3D]   = create_texture( "..\\Media\\textures\\intile3d.tga" ) ) ) return 0;
  1809.         if( !( textures[TEX_PALMTREE]   = create_texture( "..\\Media\\textures\\palmtree.tga" ) ) ) return 0;
  1810.         if( !( textures[TEX_PINETREE]   = create_texture( "..\\Media\\textures\\pinetree.tga" ) ) ) return 0;
  1811. #endif
  1812.  
  1813.         return 1;
  1814. }
  1815.  
  1816. void uninit_textures()
  1817. {
  1818.         delete_textures( MAX_TEXTURES, textures );
  1819. }
  1820.  
  1821. unsigned int get_texture( char* texname )
  1822. {
  1823.         int i = 0;
  1824.  
  1825.         /* Loop through each texture and find one with a matching name. */
  1826.         /* When the '.' signifying the end of the texture's name is reached. */
  1827.         while( i < MAX_TEXTURES )
  1828.         {
  1829.                 int c = 0;
  1830.                 int match = 1;
  1831.                 char str[16];
  1832.  
  1833.                 /* Test the file name against the current one on the list */
  1834.                 strcpy( str, tex_files[i] );
  1835.  
  1836.                 while( str[c] != '.' )
  1837.                 {
  1838.                         if( str[c] != texname[c] )
  1839.                         {
  1840.                                 match = 0;
  1841.                                 break;
  1842.                         }
  1843.  
  1844.                         c++;
  1845.                 }
  1846.  
  1847.                 /* If it matches, return that texture */
  1848.                 if( match )
  1849.                         return textures[i];
  1850.  
  1851.                 i++;
  1852.         }
  1853.  
  1854.         return 0;
  1855. }
  1856.  
  1857. int init_soundfx()
  1858. {
  1859.         HFASTFILE               ff = NULL;
  1860.         struct _iobuf*  fp = NULL;
  1861.         struct _iobuf*  out = NULL;
  1862.         int                             i = 0;
  1863.         int                             failed = 0;
  1864.  
  1865. #if 0
  1866.         /* Try to open data01.dat */
  1867.         out = fopen( "data01.dat", "r" );
  1868.  
  1869.         /* If it's there, read the fastfile attributes from there. */
  1870.         /* If not, then either create it ourselves or just fail (release builds) */
  1871.         if( !out )
  1872.         {
  1873.                 /* Create a data file to contain the sizes of each wav file */
  1874.                 out = fopen( "data01.dat", "w" );
  1875.                 fprintf( out, "files: %d\n\n", MAX_SOUNDFX );
  1876.  
  1877.                 /* Retrieve the file size of each wav file (TEMPORARY) */
  1878.                 while( i < MAX_SOUNDFX )
  1879.                 {
  1880.                         char filename[128];
  1881.  
  1882.                         sprintf( filename, "..\\Media\\sounds\\%s", sfx_files[i] );
  1883.                         fp = fopen( filename, "rb" );
  1884.                         if( !fp )
  1885.                         {
  1886.                                 MessageBox( NULL, filename, "Pale Dragon", MB_OK );
  1887.                                 return 0;
  1888.                         }
  1889.  
  1890.                         fseek( fp, 0, SEEK_END );
  1891.                         tex_file_sizes[i] = ftell( fp );
  1892.  
  1893.                         if( out )
  1894.                                 fprintf( out, "%d\n", sfx_file_sizes[i] );
  1895.  
  1896.                         fclose(fp);
  1897.  
  1898.                         i++;
  1899.                 }
  1900.         }
  1901.         else
  1902.         {
  1903.                 int files = 0;
  1904.  
  1905.                 /* Get the number of files within this fastfile */
  1906.                 fscanf( out, "files: %d\n\n", &files );
  1907.  
  1908.                 /* Get the sizes of each file within this fastfile */
  1909.                 while( i < files )
  1910.                 {
  1911.                         fscanf( out, "%d\n", &tex_file_sizes[i] );
  1912.                         i++;
  1913.                 }
  1914.         }
  1915.  
  1916.         /* Close the data file */
  1917.         if( out )
  1918.                 fclose( out );
  1919.  
  1920.         /* Initialize the fastfile */
  1921.         if( !FastFileInit( "data01.bin", MAX_SOUNDFX ) )
  1922.                 return 0;
  1923.  
  1924.         /* Start loading files from the fast file */
  1925.         i = 0;
  1926.         while( i < MAX_SOUNDFX )
  1927.         {
  1928.                 /* Get a handle to the file */
  1929.                 ff = FastFileOpen( sfx_files[i] );
  1930.                 if(ff)
  1931.                 {
  1932.                         /* If we find the file, allocate a buffer large enough so it can
  1933.                            be read as a file in memory */
  1934.                         ALubyte* buffer = (ALubyte*) malloc( sfx_file_sizes[i] );
  1935.  
  1936.                         /* Now actually read in the file's data */
  1937.                         FastFileRead( ff, buffer, sfx_file_sizes[i] );
  1938.  
  1939.                         /* Now that we have a valid file pointer with data, create a
  1940.                            wav file from it */
  1941.                        
  1942.                         sfx[i].position.x = 0.0f;
  1943.                         sfx[i].position.y = 0.0f;
  1944.                         sfx[i].position.z = 0.0f;
  1945.  
  1946.                         sfx[i].velocity.z = 0.0f;
  1947.                         sfx[i].velocity.y = 0.0f;
  1948.                         sfx[i].velocity.x = 0.0f;
  1949.  
  1950.                         sfx[i].pitch = 1.0f;
  1951.  
  1952.                         if( !create_sound_wav_from_memory( buffer, &sfx[i] ) )
  1953.                                 failed++;
  1954.  
  1955.                         /* Free the buffer */
  1956.                         free( buffer );
  1957.  
  1958.                         /* Close the fastfile handle */
  1959.                         FastFileClose( ff );
  1960.                 }
  1961.                 else
  1962.                 {
  1963.                         failed++;
  1964.                 }
  1965.  
  1966.                 i++;
  1967.         }
  1968.  
  1969.         /* Uninitialize the fast file */
  1970.         FastFileFini();
  1971.  
  1972.         /* Show any failed wav loads */
  1973.         if( failed )
  1974.         {
  1975.                 char string[64];
  1976.  
  1977.                 sprintf( string, "%d out of %d failed wav loads!", failed, MAX_SOUNDFX );
  1978.                 MessageBox( NULL, string, "Pale Dragon", MB_OK );
  1979.         }
  1980. #else
  1981.         struct sound_t snd;
  1982.  
  1983.         /* Set default values for sound effects */
  1984.         while( i < MAX_SOUNDFX )
  1985.         {
  1986.                 memcpy( &sfx[i], &snd, sizeof( struct sound_t ) );
  1987.                 i++;
  1988.         }
  1989.  
  1990.         /* Load each sound effect from disk */
  1991.         i = 0;
  1992.         if( !create_sound_wav( "..\\media\\sounds\\crystal3.wav", &sfx[i] ) ) return 0; i++;
  1993.         if( !create_sound_wav( "..\\media\\sounds\\firefa.wav", &sfx[i] ) ) return 0; i++;
  1994.         if( !create_sound_wav( "..\\media\\sounds\\hblast.wav", &sfx[i] ) ) return 0; i++;
  1995.         if( !create_sound_wav( "..\\media\\sounds\\lock.wav", &sfx[i] ) ) return 0; i++;
  1996.         if( !create_sound_wav( "..\\media\\sounds\\mmove.wav", &sfx[i] ) ) return 0; i++;
  1997.         if( !create_sound_wav( "..\\media\\sounds\\msel.wav", &sfx[i] ) ) return 0; i++;
  1998. //      if( !create_sound_au( "..\\media\\sounds\\msel.au", &sfx[i] ) ) return 0; i++;
  1999.         if( !create_sound_wav( "..\\media\\sounds\\woosh2.wav", &sfx[i] ) ) return 0; i++;
  2000.         if( !create_sound_wav( "..\\media\\sounds\\expl1s.wav", &sfx[i] ) ) return 0; i++;
  2001.         if( !create_sound_wav( "..\\media\\sounds\\gold2.wav", &sfx[i] ) ) return 0; i++;
  2002.         if( !create_sound_wav( "..\\media\\sounds\\expl2s.wav", &sfx[i] ) ) return 0; i++;
  2003.         if( !create_sound_wav( "..\\media\\sounds\\firefa2.wav", &sfx[i] ) ) return 0; i++;
  2004.  
  2005. #endif
  2006.  
  2007.         play_sound_effect_static( &sfx[5], 0 );
  2008.  
  2009.         return 1;
  2010. }
  2011.  
  2012. void uninit_soundfx()
  2013. {
  2014.         int i = 0;
  2015.  
  2016.         while( i < MAX_SOUNDFX )
  2017.         {
  2018.                 delete_sound( &sfx[i] );
  2019.                 i++;
  2020.         }
  2021. }
  2022.  
  2023. int init_fonts()
  2024. {
  2025.         int size = 0;
  2026.  
  2027.         /* Initialize fonts */
  2028.         memset( fonts, 0, sizeof( struct font_t ) * 7 );
  2029.  
  2030.         /* Small font */
  2031.         fonts[0].has_colour_key = 1;
  2032.         fonts[0].width = 160.0f;
  2033.         fonts[0].height = 64.0f;
  2034.         fonts[0].letter_width = 160.0f/20.0f;
  2035.         fonts[0].letter_height = 60.0f/5.0f;
  2036.         fonts[0].letter_offset = 0;
  2037.         fonts[0].texname = "sfont.tga";
  2038.         fonts[0].texsize = 40991;
  2039.  
  2040.         if( !init_font( &fonts[0] ) )
  2041.                 return 0;
  2042.  
  2043.         /* Medium font */
  2044.         fonts[1].has_colour_key = 1;
  2045.         fonts[1].width = 256.0f;
  2046.         fonts[1].height = 256.0f;
  2047.         fonts[1].letter_width = 16.0f;
  2048.         fonts[1].letter_height = 16.0f;
  2049.         fonts[1].letter_offset = 5.0f;
  2050.         fonts[1].texname = "mfont.tga";
  2051.         fonts[1].texsize = 262175;
  2052.  
  2053.         if( !init_font( &fonts[1] ) )
  2054.                 return 0;
  2055.  
  2056.         /* Medium font */
  2057.         fonts[2].has_colour_key = 1;
  2058.         fonts[2].width = 512.0f;
  2059.         fonts[2].height = 512.0f;
  2060.         fonts[2].letter_width = 32.0f;
  2061.         fonts[2].letter_height = 32.0f;
  2062.         fonts[2].letter_offset = 16.0f;
  2063.         fonts[2].texname = "lfont.tga";
  2064.         fonts[2].texsize = 1048607;
  2065.  
  2066.         if( !init_font( &fonts[2] ) )
  2067.                 return 0;
  2068.  
  2069.         /* Small font 2 */
  2070.         fonts[FONT_SMALL2].has_colour_key = 1;
  2071.         fonts[FONT_SMALL2].width = 181.0f;
  2072.         fonts[FONT_SMALL2].height = 56.0f;
  2073.         fonts[FONT_SMALL2].letter_width = 9.0f;//180.0f/20.0f;
  2074.         fonts[FONT_SMALL2].letter_height = 11.0f;//55.0f/5.0f;
  2075.         fonts[FONT_SMALL2].letter_offset = 1.0f;
  2076.         fonts[FONT_SMALL2].texname = "sfont2.tga";
  2077.         fonts[FONT_SMALL2].texsize = 11883;//39644;
  2078.         fonts[FONT_SMALL2].char_offset = 0;//249;
  2079.  
  2080.         if( !init_font( &fonts[FONT_SMALL2] ) )
  2081.                 return 0;
  2082.  
  2083.         /* Menu font */
  2084.         fonts[FONT_MENU].has_colour_key = 1;
  2085.         fonts[FONT_MENU].width = 258.0f;
  2086.         fonts[FONT_MENU].height = 99.0f;
  2087.         fonts[FONT_MENU].letter_width = 258.0f/16.0f;
  2088.         fonts[FONT_MENU].letter_height = 99.0f/6.0f;
  2089.         fonts[FONT_MENU].letter_offset = 6.0f;
  2090.         fonts[FONT_MENU].texname = "menufont.tga";
  2091.         fonts[FONT_MENU].texsize = 102199;
  2092.  
  2093.         if( !init_font( &fonts[FONT_MENU] ) )
  2094.                 return 0;
  2095.  
  2096.         /* Violet font */
  2097.         fonts[FONT_BOLD].has_colour_key = 1;
  2098.         fonts[FONT_BOLD].width = 255.0f;
  2099.         fonts[FONT_BOLD].height = 109.0f;
  2100.         fonts[FONT_BOLD].letter_width = 255.0f/16.0f;
  2101.         fonts[FONT_BOLD].letter_height = 109.0f/6.0f;
  2102.         fonts[FONT_BOLD].letter_offset = 0.0f;
  2103.         fonts[FONT_BOLD].texname = "7X8B2.tga";
  2104.         fonts[FONT_BOLD].texsize = 111211;
  2105.  
  2106.         if( !init_font( &fonts[FONT_BOLD] ) )
  2107.                 return 0;
  2108.  
  2109.         /* Steel font */
  2110.         fonts[FONT_STEEL].has_colour_key = 1;
  2111.         fonts[FONT_STEEL].width = 225.0f;
  2112.         fonts[FONT_STEEL].height = 79.0f;
  2113.         fonts[FONT_STEEL].letter_width = 225.0f/16.0f;
  2114.         fonts[FONT_STEEL].letter_height = 79.0f/6.0f;
  2115.         fonts[FONT_STEEL].letter_offset = 5.0f;
  2116.         fonts[FONT_STEEL].texname = "fsteel.tga";
  2117.         fonts[FONT_STEEL].texsize = 71144;
  2118.  
  2119.         if( !init_font( &fonts[FONT_STEEL] ) )
  2120.                 return 0;
  2121.  
  2122.         return 1;
  2123. }
  2124.  
  2125. void uninit_fonts()
  2126. {
  2127.         int i = 0;
  2128.  
  2129.         while( i < 7 )
  2130.         {
  2131.                 uninit_font( &fonts[i] );
  2132.                 i++;
  2133.         }
  2134. }
  2135.  
  2136. int init_splines( int stage )
  2137. {
  2138.         /* Initialise splines for a given stage */
  2139.  
  2140.         char dir[32];
  2141.         int i = 0;
  2142.         struct _iobuf* fp = NULL;
  2143.         struct Vector2 p[32];
  2144.  
  2145.         sprintf( dir, "st%02d\\spline002.dat", stage );
  2146.  
  2147.         fp = fopen( dir, "rb" );
  2148.  
  2149.         if( !fp )
  2150.                 return 0;
  2151.  
  2152.         fread( &spline.num_base_points, 1, sizeof( int ), fp );
  2153.         fread( &spline.tesselation, 1, sizeof( int ), fp );
  2154.         fread( p, 1, sizeof( struct Vector2 ) * spline.num_base_points, fp );
  2155.  
  2156.         fclose(fp);
  2157.  
  2158.         return create_spline( &spline, p, spline.num_base_points, spline.tesselation, 5.0f );
  2159. }
  2160.  
  2161. void uninit_splines()
  2162. {
  2163.         delete_spline( &spline );
  2164. }
  2165.  
  2166. void reset_homing_blasts();
  2167. void reset_fullautoblasts();
  2168.  
  2169. int init_game()
  2170. {
  2171.         /*if(AllocConsole())
  2172.         {
  2173.                 freopen("CONOUT$", "wt", stdout);
  2174.                 SetConsoleTitle(L"MyApp : Debug Console");
  2175.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
  2176.         }*/
  2177.  
  2178.         /* TEST: Initialize splines */ 
  2179.         if( !init_splines(0) )
  2180.                 return 0;
  2181.  
  2182.         /* Seed random number generator */
  2183.         srand( time( NULL ) );
  2184.         /* Reset the player's dragon attributes */
  2185.         reset_dragon();
  2186.         /* Reset lock icons */
  2187.         reset_all_locks( FALSE );
  2188.         /* Reset all enemies */
  2189.         reset_enemies();
  2190.         /* Reset all homing blasts */
  2191.         reset_homing_blasts();
  2192.         /* Reset all fullauto blasts */
  2193.         reset_fullautoblasts();
  2194.         /* Reset explosions */
  2195.         memset( explosions, 0, sizeof( struct explosion_t ) );
  2196.         /* Reset powerups */
  2197.         reset_powerups();
  2198.         /* Reset smoke puffs */
  2199.         reset_smoke_puffs();
  2200.         /* Reset enemy shoots */
  2201.         reset_enemy_shoots();
  2202.  
  2203.         /* TEST: Boss */
  2204.         if( !boss_mode )
  2205.                 init_boss(1);
  2206.  
  2207.         /* Set input type */
  2208.         set_input_type(0);
  2209.  
  2210.         /* Reset mouse position */
  2211.         center_mouse();
  2212.  
  2213.         /* Create a render target */
  2214.         render_target = create_texture_rectangle( 640, 480, 32 );
  2215.         if( !render_target )
  2216.                 return 0;
  2217.  
  2218.         /* Initialize gold cache */
  2219.         if( !init_gold_cache( 2000 ) )
  2220.                 return 0;
  2221.  
  2222.         /* Initialize textures */
  2223.         if( !init_textures() )
  2224.                 return 0;
  2225.  
  2226.         /* Initialize sound effects */
  2227.         if( !init_soundfx() )
  2228.                 return 0;
  2229.  
  2230.         /* Initialize fonts */
  2231.         if( !init_fonts() )
  2232.                 return 0;
  2233.  
  2234.         /* Initialize menu data */
  2235.         if( !init_menus() )
  2236.                 return 0;
  2237.  
  2238.         /* BGM test */
  2239.         if( !wavestream_open( "00.wav", &bgm ) )
  2240.                 return 0;
  2241.  
  2242. //      wavestream_play(&bgm);
  2243.  
  2244.         return 1;
  2245. }
  2246.  
  2247. void uninit_game()
  2248. {
  2249.         /* Uninit textures and sound effects */
  2250.         uninit_splines();
  2251.         wavestream_close(&bgm);
  2252.         uninit_menus();
  2253.         uninit_fonts();
  2254.         uninit_soundfx();
  2255.         uninit_textures();
  2256.         uninit_gold_cache();
  2257.         delete_textures( 1, &render_target );
  2258. }
  2259.  
  2260. void draw_background()
  2261. {
  2262.         /* Draw the background image */
  2263.         enable_2d();
  2264.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2265.         draw_quad( get_texture( tex_files[background+2] ), 0.0f, 0.0f, 640.0f, 480.0f );
  2266.         disable_2d();
  2267. }
  2268.  
  2269. void draw_environment()
  2270. {
  2271.         float tex[] = { 0.0f, 10.0f, 15.0f, 10.0f, 15.0f, 0.0f, 0.0f, 0.0f };
  2272.         static float h1 = 0;
  2273.         static float h2 = -480.0f;
  2274.         static int setup_trees_n_stuff = 0; /* Temporary */
  2275.         int i = 0;
  2276. //      static float tree_x = 160.0f;//(float) ( rand() % 320 );
  2277. //      static float tree_y = -121.0f;
  2278.  
  2279.         /* Place trees at random places */
  2280.         if( !setup_trees_n_stuff )
  2281.         {
  2282.                 i = 0;
  2283.  
  2284.                 setup_trees_n_stuff = 1;
  2285.  
  2286.                 while( i < 8 )
  2287.                 {
  2288.                         trees[i].x = (float) ( rand() % ( 320 - 121 ) ) + 160;
  2289.                         trees[i].y = (float) -( rand() % 480 ) + 121;
  2290.                         i++;
  2291.                 }
  2292.         }
  2293.  
  2294.         /* Draw the menu and ingame boundaries */
  2295.         enable_2d();
  2296.  
  2297.         /* First half of the scrolling effect */
  2298.         push_pos();
  2299.         translate( 640.0f/4.0f, h1 );
  2300.         set_colour( 0.0f, 0.0f, 0.0f, 1.0f );
  2301.         draw_quad( 0, 0.0f, 0.0f, 640.0f/2.0f, 480.0f );
  2302.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2303.         draw_quad2( get_texture( "grass1a" ), tex, 0.0f, 0.0f, 640.0f/2.0f, 480.0f );
  2304.         pop_pos();
  2305.  
  2306.         /* Second half of the scrolling effect */
  2307.         push_pos();
  2308.         translate( 640.0f/4.0f, h2 );
  2309. //      set_colour( 0.0f, 0.0f, 0.0f, 1.0f );
  2310. //      draw_quad( 0, 0.0f, 0.0f, 640.0f/2.0f, 480.0f );
  2311.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2312.         draw_quad2( get_texture( "grass1a" ), tex, 0.0f, 0.0f, 640.0f/2.0f, 480.0f );
  2313.         pop_pos();
  2314.  
  2315.         push_pos();
  2316. //      translate( 640.0f/4.0f, 0.0f );
  2317.         transparent_blend( TRUE );
  2318.  
  2319.         i = 0;
  2320.         while( i < 8 )
  2321.         {
  2322.                 draw_quad( get_texture( "palmtree" ), trees[i].x, trees[i].y, 101.0f, 121.0f );
  2323.                 i++;
  2324.         }
  2325.  
  2326.         transparent_blend( FALSE );
  2327.         pop_pos();
  2328.  
  2329.         disable_2d();
  2330.  
  2331.         h1 += scroll_speed;
  2332.         h2 += scroll_speed;
  2333.  
  2334.         if( h1 >= 480.0f )
  2335.                 h1 = 0.0f;
  2336.         if( h2 >= 0.0f )
  2337.                 h2 = -480.0f;
  2338.  
  2339.         /* Update trees 'n stuff */
  2340.         if( setup_trees_n_stuff )
  2341.         {
  2342.                 i = 0;
  2343.  
  2344.                 while( i < 8 )
  2345.                 {
  2346.                         trees[i].y += scroll_speed;
  2347.  
  2348.                         if( trees[i].y >= 480.0f )
  2349.                         {
  2350.                                 trees[i].y = (float) -(( rand() % 480 ) + 121);
  2351.                                 trees[i].x = (float) (rand() % (320-121))+160;
  2352.                         }
  2353.  
  2354.                         i++;
  2355.                 }
  2356.         }
  2357. }
  2358.  
  2359. void draw_boundaries()
  2360. {
  2361.         float tex1[] = { 0.0f, 1.0f, 0.25f, 1.0f, 0.25f, 0.0f, 0.0f, 0.0f };
  2362.         float tex2[] = { 0.75f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.75f, 0.0f };
  2363.  
  2364.         /* Draw the play area boundaries */
  2365.         enable_2d();
  2366.  
  2367.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2368.  
  2369.         /* Helps hide things outside of the game's boundaries */
  2370.         push_pos();
  2371.         draw_quad2( get_texture( tex_files[background+2] ), tex1, 0, 0, 160, 480 );
  2372.         translate( 480.0f, 0.0f );
  2373.         draw_quad2( get_texture( tex_files[background+2] ), tex2, 0, 0, 160, 480 );
  2374.         pop_pos();
  2375.  
  2376.         push_pos();
  2377.         translate( 640.0f/4.0f, 0.0f );
  2378.         draw_line( 0.0f, 0.0f, 0.0f, 480.0f );
  2379.         draw_line( 640.0f/2.0f+1.0f, 0.0f, 640.0f/2.0f+1.0f, 480.0f );
  2380.         pop_pos();
  2381.  
  2382.         disable_2d();
  2383. }
  2384.  
  2385. void get_attack_mode_changes()
  2386. {
  2387.         static int change = 0;
  2388.  
  2389.         /* Change attack mode when the right mouse button is clicked */
  2390.         if( changefire_button_down() && !change )
  2391.         {
  2392.                 change = 1;
  2393.                 dragon.attack_mode = !dragon.attack_mode;
  2394.  
  2395.                 /* If we are switching to full auto, release all locks on
  2396.                 any targeted enemies since it will be of no use to us. */
  2397.                 if( dragon.attack_mode == 0 )
  2398.                         reset_all_locks( TRUE );
  2399.         }
  2400.  
  2401.         /* Only register one click */
  2402.         if( !changefire_button_down() && change )
  2403.                 change = 0;
  2404. }
  2405.  
  2406. void draw_crosshair()
  2407. {
  2408.         float size = dragon.attack_mode == 0 ? 128.0f : 64.0f;
  2409.         unsigned int ch_tex = dragon.attack_mode == 0 ?
  2410.                 get_texture( "cross2" ) : get_texture( "cross1" );
  2411.         float x = ch.x;
  2412.         float y = ch.y;
  2413.  
  2414.         if( x < 160.0f )
  2415.                 x = 160.0f;
  2416.         if( x > 480.0f )
  2417.                 x = 480.0f;
  2418.         if( y < 0.0f )
  2419.                 y = 0.0f;
  2420.         if( y > 480.0f )
  2421.                 y = 480.0f;
  2422.  
  2423.         /* Draw the crosshair  */
  2424.         enable_2d();
  2425.         transparent_blend( TRUE );
  2426.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2427.         translate( x-(size/2.0f), y-(size/2.0f) );
  2428.         draw_quad( ch_tex, 0.0f, 0.0f, size, size );
  2429.         transparent_blend( FALSE );
  2430.         disable_2d();
  2431. }
  2432.  
  2433. void acquire_new_locks()
  2434. {
  2435.         /* Only check for locks when in lock mode */
  2436.         /* Don't check if we are using full auto */
  2437.         if( dragon.attack_mode == 1 )
  2438.         {
  2439.                 int i = 0;
  2440.  
  2441.                 /* Loop though the list of enemies and check for locks */
  2442.                 while( i < MAX_ENEMIES )
  2443.                 {
  2444.                         /* Check all enemies that aren't dead and that don't already have a lock acquired */
  2445.                         if( !enemies[i].dead && !enemies[i].dying && enemies[i].lock == -1 && shoot_button_down() )
  2446.                         {
  2447.                                 /* Check to see of the crosshair has caught this enemy */
  2448.                                 if( ch.x > enemies[i].x-(enemies[i].sx/2.0f) && ch.x < enemies[i].x+(enemies[i].sx/2.0f) )
  2449.                                 {
  2450.                                         if( ch.y > enemies[i].y-(enemies[i].sy/2.0f) && ch.y < enemies[i].y+(enemies[i].sy/2.0f) )
  2451.                                         {
  2452.                                                 /* We got a lock! Now check if there are any free locks */
  2453.                                                 int lock = find_inactive_lock();
  2454.                                                 if( lock != -1 )
  2455.                                                 {
  2456.                                                         /* We have a free lock! Release the shoot button and blow this sucker away! */
  2457.                                                         enemies[i].lock = lock;
  2458.                                                         locks[lock].owner = i;
  2459.                                                         activate_lock( lock, enemies[i].x, enemies[i].y );
  2460.                                                         play_sound_effect_static( &sfx[3], 0 );
  2461.                                                 }
  2462.                                         }
  2463.                                 }
  2464.                         }
  2465.  
  2466.                         i++;
  2467.                 }
  2468.         }
  2469. }
  2470.  
  2471. void reset_homing_blasts()
  2472. {
  2473.         int i = 0;
  2474.  
  2475.         /* Reset all homing blasts */
  2476.         memset( homingblasts, 0, sizeof( struct homingblast_t ) * MAX_HOMINGBLASTS );
  2477.  
  2478.         while( i < MAX_HOMINGBLASTS )
  2479.         {
  2480.                 homingblasts[i].target = -1;
  2481.                 homingblasts[i].fade_timer = 200;
  2482.                 homingblasts[i].sx = homingblasts[i].sy = 32.0f;
  2483.                 i++;
  2484.         }
  2485. }
  2486.  
  2487. int active_homing_blasts()
  2488. {
  2489.         int i = 0;
  2490.         int count = 0;
  2491.  
  2492.         /* Return the number of active homing blasts */
  2493.         while( i < MAX_HOMINGBLASTS )
  2494.         {
  2495.                 if( homingblasts[i].target != -1 )
  2496.                         count++;
  2497.  
  2498.                 i++;
  2499.         }
  2500.  
  2501.         return count;
  2502. }
  2503.  
  2504. void ready_homing_blasts()
  2505. {
  2506.         int i = 0;
  2507.         int j = 0;
  2508.  
  2509.         /* Assign each targetable entity a seperate homing blast to destroy it */
  2510.         /* Limit the number of homing blasts assigned to MAX_HOMINGBLASTS. */
  2511.         while( i < MAX_ENEMIES )
  2512.         {
  2513.                 if( enemies[i].lock != -1 )
  2514.                 {
  2515.                         homingblasts[j].target = i;
  2516.                         homingblasts[j].fade_timer = 200;
  2517.                         homingblasts[j].x = dragon.x+(dragon.width/2.0f);
  2518.                         homingblasts[j++].y = dragon.y+(dragon.height/2.0f);
  2519.  
  2520.                         if( j == MAX_HOMINGBLASTS )
  2521.                                 break;
  2522.                 }
  2523.  
  2524.                 i++;
  2525.         }
  2526. }
  2527.  
  2528. void clamp_float( float* d, float min, float max )
  2529. {
  2530.         if( *d < min )
  2531.                 *d = min;
  2532.  
  2533.         if( *d > max )
  2534.                 *d = max;
  2535. }
  2536.  
  2537. #if 0
  2538. void test_track()
  2539. {
  2540.         static struct Vector2 p = { 0.0f, 320.0f };
  2541.         static struct Vector2 v = { 0.0f, 0.0f };
  2542.  
  2543.         float angle_to_player = angle( p.x, p.y, dragon.x, dragon.y );
  2544.         float speed = 10.0f;
  2545.  
  2546.         v.x += cos(angle_to_player);
  2547.         v.y += sin(angle_to_player);
  2548.  
  2549.         clamp_float( &v.x, -speed, speed );
  2550.         clamp_float( &v.y, -speed, speed );
  2551.  
  2552.         p.x += v.x;
  2553.         p.y += v.y;
  2554.  
  2555.         enable_2d();
  2556.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2557.         transparent_blend(TRUE);
  2558.         draw_quad( get_texture("hblast2"), p.x+(106.0f/2.0f), p.y+(149.0f/2.0f), 32.0f, 32.0f );
  2559.         transparent_blend(FALSE);
  2560.         disable_2d();
  2561. }
  2562. #endif
  2563.  
  2564. void draw_homing_blasts()
  2565. {
  2566.         int i = 0;
  2567.  
  2568.         /* Draw each active homing blast */
  2569.         enable_2d();
  2570.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2571.         transparent_blend( TRUE );
  2572.  
  2573.         while( i < MAX_HOMINGBLASTS )
  2574.         {
  2575.                 if( homingblasts[i].target != -1 )
  2576.                 {
  2577.                         draw_quad( get_texture( "hblast2" ),
  2578.                                 homingblasts[i].x-(homingblasts[i].sx/2.0f),
  2579.                                 homingblasts[i].y-(homingblasts[i].sy/2.0f),
  2580.                                 homingblasts[i].sx, homingblasts[i].sy );
  2581.                 }
  2582.  
  2583.                 i++;
  2584.         }
  2585.  
  2586.         transparent_blend( FALSE );
  2587.         disable_2d();
  2588. }
  2589.  
  2590. void update_homing_blasts()
  2591. {
  2592.         int i = 0;
  2593.  
  2594.         while( i < MAX_HOMINGBLASTS )
  2595.         {
  2596.                 if( homingblasts[i].target != -1 )
  2597.                 {
  2598.                         float angle_to_target = angle( homingblasts[i].x, homingblasts[i].y,
  2599.                                 enemies[homingblasts[i].target].x /*-(enemies[homingblasts[i].target].sx/2.0f)*/,
  2600.                                 enemies[homingblasts[i].target].y /*-(enemies[homingblasts[i].target].sy/2.0f)*/ );
  2601.                         float speed = 10.0f;
  2602.                         float cx = 0, cy = 0;
  2603.  
  2604.                         homingblasts[i].vx += cos(angle_to_target);
  2605.                         homingblasts[i].vy += sin(angle_to_target);
  2606.  
  2607. #if 0
  2608.                         clamp_float( &homingblasts[i].vx, -speed, speed );
  2609.                         clamp_float( &homingblasts[i].vy, -speed, speed );
  2610. #else
  2611.                         cx = cos( angle_to_target );
  2612.                         cy = sin( angle_to_target );
  2613.                 //      cx = (abs(cx));
  2614.                 //      cy = (abs(cy));
  2615.  
  2616.                         clamp_float( &homingblasts[i].vx, -speed*cx, speed*cx );
  2617.                         clamp_float( &homingblasts[i].vy, -speed*cy, speed*cy );
  2618. #endif
  2619.  
  2620.                         homingblasts[i].x += homingblasts[i].vx;
  2621.                         homingblasts[i].y += homingblasts[i].vy;
  2622.                 }
  2623.  
  2624.                 /* If this homing blast expires, let it shrink and set it as inactive */
  2625.                 if( --homingblasts[i].fade_timer <= 0 )
  2626.                 {
  2627.                         homingblasts[i].sx -= 0.5f;
  2628.                         homingblasts[i].sy -= 0.5f;
  2629.                        
  2630.                         if( homingblasts[i].sx <= 1.0f )
  2631.                         {
  2632.                                 homingblasts[i].target = -1;
  2633.                                 homingblasts[i].fade_timer = 200;
  2634.                                 homingblasts[i].sx = homingblasts[i].sy = 32.0f;
  2635.                         }
  2636.                 }
  2637.  
  2638.                 i++;
  2639.         }
  2640. }
  2641.  
  2642. void check_homing_blasts_for_collisions()
  2643. {
  2644.         int i = 0;
  2645.  
  2646.         /* Check each homing blast for a collision with an enemy. */
  2647.         /* If we get a hit, then mark the enemy as dead and the homing blast
  2648.            as inactive and stop updating it. */
  2649.         while( i < MAX_HOMINGBLASTS )
  2650.         {
  2651.                 /* Is this homing blast even tracking anything? */
  2652.                 if( homingblasts[i].target != -1 )
  2653.                 {
  2654.                         /* Looks like it is. Let's see if it hit anything! */
  2655.                         /* The collision rect is (should be) a constant 32x32 pixels
  2656.                            which is centered around the center of the targetable entity. */
  2657.                         int j = 0;
  2658.                         while( j < MAX_ENEMIES )
  2659.                         {
  2660.                                 /* Target only living enemies */
  2661.                                 if( !enemies[j].dead && !enemies[j].dying )
  2662.                                 {
  2663.                                         /* Good, it's alive. Now, did we actually hit it? */
  2664.                                         if( homingblasts[i].x >= (enemies[j].x-(enemies[j].sx/2.0f)) &&
  2665.                                                 homingblasts[i].x <= (enemies[j].x+(enemies[j].sx/2.0f)) &&
  2666.                                                 homingblasts[i].y >= (enemies[j].y-(enemies[j].sy/2.0f)) &&
  2667.                                                 homingblasts[i].y <= (enemies[j].y+(enemies[j].sy/2.0f)) )
  2668.                                         {
  2669.                                                 /* Do 5 damage */
  2670.                                                 enemies[j].energy -= 5;
  2671.  
  2672.                                                 /* Is this enemy dead? */
  2673.                                                 if( enemies[j].energy <= 0 )
  2674.                                                 {
  2675.                                                         /* Enemy zeppelin's don't die automatically */
  2676.                                                         if( enemies[j].type == ENEMY_ZEPPELIN )
  2677.                                                                 enemies[j].dying = Yes;
  2678.                                                         else
  2679.                                                         {
  2680.                                                                 /* Katsu! */
  2681.                                                                 kill_enemy( &enemies[j], 7 );
  2682.                                                         }
  2683.                                                 }
  2684.                                                 else
  2685.                                                 {
  2686.                                                         /* If not, just flash white for a frame */
  2687.                                                         enemies[j].flash = Yes;
  2688.                                                 }
  2689.                                                
  2690.                                                 /* Let homing blast go */
  2691.                                                 homingblasts[i].target = -1;
  2692.                                                 homingblasts[i].fade_timer = 200;
  2693.                                                 homingblasts[i].sx = homingblasts[i].sy = 32.0f;
  2694.  
  2695.                                                 break;
  2696.                                         }
  2697.                                 }
  2698.  
  2699.                                 j++;
  2700.                         }
  2701.                 }
  2702.  
  2703.                 i++;
  2704.         }
  2705. }
  2706.  
  2707. void reset_fullautoblasts()
  2708. {
  2709.         /* Reset all full auto blasts */
  2710.         memset( fullautoblasts, 0, sizeof( struct fullautoblast_t ) * MAX_FULLAUTOBLASTS );
  2711. }
  2712.  
  2713. int find_inactive_fullautoblast()
  2714. {
  2715.         int i = 0;
  2716.  
  2717.         /* Finds an inactive fullauto blast. If we find one, return that id number.
  2718.            If not, return -1 for a failure to find one */
  2719.         while( i < MAX_FULLAUTOBLASTS )
  2720.         {
  2721.                 if( !fullautoblasts[i].active )
  2722.                         return i;
  2723.  
  2724.                 i++;
  2725.         }
  2726.  
  2727.         return -1;
  2728. }
  2729.  
  2730. void activate_fullautoblast( int id )
  2731. {
  2732.         /* Activate full auto blast and initialize the variables that make it "go"! */
  2733.  
  2734.         fullautoblasts[id].active = Yes;
  2735.         fullautoblasts[id].x = dragon.x + (dragon.width/2.0f);
  2736.         fullautoblasts[id].y = dragon.y + (dragon.height/2.0f);
  2737.         fullautoblasts[id].size = ( overdrive_timer > 0 ) ? 64.0f : 32.0f;
  2738.  
  2739.         fullautoblasts[id].angle = angle( dragon.x+(dragon.width/2.0f), dragon.y+(dragon.height/2.0f),
  2740.                 ch.x, ch.y );
  2741.         fullautoblasts[id].dirx = cos( fullautoblasts[id].angle );
  2742.         fullautoblasts[id].diry = sin( fullautoblasts[id].angle );
  2743.         fullautoblasts[id].speed = 15.0f;
  2744. }
  2745.  
  2746. void draw_fullautoblasts()
  2747. {
  2748.         int i = 0;
  2749.  
  2750.         /* Draw each active fullauto blast */
  2751.         enable_2d();
  2752.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  2753.         transparent_blend( TRUE );
  2754.  
  2755.         while( i < MAX_FULLAUTOBLASTS )
  2756.         {
  2757.                 if( fullautoblasts[i].active )
  2758.                 {
  2759.                         if( distance2d( fullautoblasts[i].x, fullautoblasts[i].y,
  2760.                                 dragon.x+(dragon.width/2.0f), dragon.y+(dragon.height/2.0f) ) > 15.0f )
  2761.                         {
  2762.                                 draw_quad( get_texture( "hblast2" ),
  2763.                                         fullautoblasts[i].x - ( fullautoblasts[i].size/2.0f ),
  2764.                                         fullautoblasts[i].y - ( fullautoblasts[i].size/2.0f ),
  2765.                                         fullautoblasts[i].size, fullautoblasts[i].size );
  2766.                         }
  2767.                 }
  2768.  
  2769.                 i++;
  2770.         }
  2771.  
  2772.         transparent_blend( FALSE );
  2773.         disable_2d();
  2774. }
  2775.  
  2776. void update_fullautoblasts()
  2777. {
  2778.         int i = 0;
  2779.  
  2780.         /* Update each fullauto blast */
  2781.         while( i < MAX_FULLAUTOBLASTS )
  2782.         {
  2783.                 /* Is this blast active ? */
  2784.                 if( fullautoblasts[i].active )
  2785.                 {
  2786.                         /* If so, then move it in the desired direction */
  2787.                         /* But before we do that, let's check to see if this blast is */
  2788.                         /* beyond the boundaries, or if it hit anything */
  2789.  
  2790.                         if( fullautoblasts[i].x <= 0 || fullautoblasts[i].x > 640 ||
  2791.                                 fullautoblasts[i].y <= 0 || fullautoblasts[i].y > 480 )
  2792.                         {
  2793.                                 /* Out of bounds */
  2794.                                 fullautoblasts[i].active = No;
  2795.                         }
  2796.  
  2797.                         fullautoblasts[i].x += fullautoblasts[i].dirx * fullautoblasts[i].speed;
  2798.                         fullautoblasts[i].y += fullautoblasts[i].diry * fullautoblasts[i].speed;
  2799.                 }
  2800.  
  2801.                 i++;
  2802.         }
  2803. }
  2804.  
  2805. void check_fullauto_blasts_for_collisions()
  2806. {
  2807.         int i = 0;
  2808.  
  2809.         /* Check each fullauto blast for a collision with any enemies */
  2810.         while( i < MAX_FULLAUTOBLASTS )
  2811.         {
  2812.                 /* Don't check any inactive ones */
  2813.                 if( fullautoblasts[i].active )
  2814.                 {
  2815.                         /* If it is, check it against each active enemy */
  2816.                         int j = 0;
  2817.  
  2818.                         /* Check each enemy for a collision test */
  2819.                         while( j < MAX_ENEMIES )
  2820.                         {
  2821.                                 /* Is this enemy alive so we can kill it? */
  2822.                                 if( !enemies[j].dead && !enemies[j].dying )
  2823.                                 {
  2824.                                         /* It is, let's check to see if the full auto blast hit it */
  2825.                                         if( fullautoblasts[i].x >= (enemies[j].x-(enemies[j].sx/2.0f)) &&
  2826.                                                 fullautoblasts[i].x <= (enemies[j].x+(enemies[j].sx/2.0f)) &&
  2827.                                                 fullautoblasts[i].y >= (enemies[j].y-(enemies[j].sy/2.0f)) &&
  2828.                                                 fullautoblasts[i].y <= (enemies[j].y+(enemies[j].sy/2.0f)) )
  2829.                                         {
  2830.                                                 /* Do 1 damage for normal, 2 for overdrive */
  2831.                                                 enemies[j].energy -= (overdrive_timer > 0) ? 2 : 1;
  2832.  
  2833.                                                 /* Is this enemy dead? */
  2834.                                                 if( enemies[j].energy <= 0 )
  2835.                                                 {
  2836.                                                         /* Enemy zeppelin's don't die automatically */
  2837.                                                         if( enemies[j].type == ENEMY_ZEPPELIN )
  2838.                                                                 enemies[j].dying = Yes;
  2839.                                                         else
  2840.                                                         {
  2841.                                                                 /* Katsu! */
  2842.                                                                 kill_enemy( &enemies[j], 7 );
  2843.                                                         }
  2844.                                                 }
  2845.                                                 else
  2846.                                                 {
  2847.                                                         /* If not, just flash white for a frame */
  2848.                                                         enemies[j].flash = Yes;
  2849.                                                 }
  2850.                                                
  2851.                                                 /* Let fullauto blast go */
  2852.                                                 fullautoblasts[i].active = No;
  2853.                                         }
  2854.                                 }
  2855.  
  2856.                                 j++;
  2857.                         }
  2858.                 }
  2859.  
  2860.                 i++;
  2861.         }
  2862. }
  2863.  
  2864. void activate_explosion( int expl_id, float x, float y, int type )
  2865. {
  2866.         explosions[expl_id].active = Yes;
  2867.         explosions[expl_id].frame = 0;
  2868.         explosions[expl_id].last_frame = 24;
  2869.         explosions[expl_id].timer = 0;
  2870.         explosions[expl_id].max_timer = 2;
  2871.         explosions[expl_id].x = x;
  2872.         explosions[expl_id].y = y;
  2873.         explosions[expl_id].sx = 320.0f / 5.0f;
  2874.         explosions[expl_id].sy = 320.0f / 5.0f;
  2875.         explosions[expl_id].type = type;
  2876. }
  2877.  
  2878. int find_inactive_explosion()
  2879. {
  2880.         int i = 0;
  2881.  
  2882.         /* Find the first inactive explosion */
  2883.         while( i < MAX_EXPLOSIONS )
  2884.         {
  2885.                 /* Is this explosion active?  If so, go to the next one.
  2886.                    If not, then return that explosion id. */
  2887.                 if( !explosions[i].active )
  2888.                         return i;
  2889.  
  2890.                 i++;
  2891.         }
  2892.  
  2893.         return -1;
  2894. }
  2895.  
  2896. void render_explosions()
  2897. {
  2898.         int i = 0;
  2899.  
  2900.         /* Render each active explosion */
  2901.         while( i < MAX_EXPLOSIONS )
  2902.         {
  2903.                 /* Is this explosion active? */
  2904.                 if( explosions[i].active )
  2905.                 {
  2906.                         /* Draw it! */
  2907.                         draw_explosion( &explosions[i] );
  2908.                 }
  2909.  
  2910.                 i++;
  2911.         }
  2912. }
  2913.  
  2914. void update_explosions()
  2915. {
  2916.         int i = 0;
  2917.  
  2918.         /* Update each active explosion */
  2919.         while( i < MAX_EXPLOSIONS )
  2920.         {
  2921.                 /* Is this explosion active? */
  2922.                 if( explosions[i].active )
  2923.                 {
  2924.                         /* Is it time to update this explosion? */
  2925.                         if( ++explosions[i].timer >= explosions[i].max_timer )
  2926.                         {
  2927.                                 /* Okay, let's move on to the next frame, then check if we reached
  2928.                                    the final frame. */
  2929.                                 explosions[i].timer = 0;
  2930.  
  2931.                                 if( ++explosions[i].frame >= explosions[i].last_frame )
  2932.                                 {
  2933.                                         /* Now that we have reached the last frame, set this explosion
  2934.                                            as inactive to be reused later */
  2935.                                         explosions[i].active = No;
  2936.                                 }
  2937.                         }
  2938.                 }
  2939.  
  2940.                 i++;
  2941.         }
  2942. }
  2943.  
  2944. void reset_smoke_puffs()
  2945. {
  2946.         memset( &smoke, 0, sizeof( struct smoke_t ) * MAX_SMOKE );
  2947. }
  2948.  
  2949. void add_smoke_puff( float x, float y, int type )
  2950. {
  2951.         int i = 0;
  2952.  
  2953.         /* Search for an unused smoke puff */
  2954.         while( i < MAX_SMOKE )
  2955.         {
  2956.                 /* Is this puff active? */
  2957.                 if( !smoke[i].active )
  2958.                 {
  2959.                         /* Activate it */
  2960.                         smoke[i].x = x;
  2961.                         smoke[i].y = y;
  2962.                         smoke[i].sx = smoke[i].sy = 4.0f;
  2963.                         smoke[i].active = Yes;
  2964.                         smoke[i].type = type;
  2965.                         break;
  2966.                 }
  2967.  
  2968.                 i++;
  2969.         }
  2970. }
  2971.  
  2972. void draw_smoke_puffs()
  2973. {
  2974.         int i = 0;
  2975.  
  2976.         /* Draw each smoke puff */
  2977.  
  2978.         enable_2d();
  2979.         transparent_blend(Yes);
  2980.  
  2981.         while( i < MAX_SMOKE )
  2982.         {
  2983.                 if( smoke[i].active )
  2984.                 {
  2985.                         push_pos();
  2986.                         translate( smoke[i].x, smoke[i].y ),
  2987.                         rotate( smoke[i].rot );
  2988.                         draw_quad( get_texture( "smoke" ), -(smoke[i].sx/2.0f), -(smoke[i].sy/2.0f), smoke[i].sx, smoke[i].sy );
  2989.                         pop_pos();
  2990.                 }
  2991.  
  2992.                 i++;
  2993.         }
  2994.  
  2995.         transparent_blend(No);
  2996.         disable_2d();
  2997. }
  2998.  
  2999. void update_smoke_puffs()
  3000. {
  3001.         int i = 0;
  3002.  
  3003.         /* Draw each smoke puff */
  3004.  
  3005.         while( i < MAX_SMOKE )
  3006.         {
  3007.                 if( smoke[i].active )
  3008.                 {
  3009.                         /* Expand the size of this smoke puff */
  3010.                         smoke[i].sx += 1.0f;
  3011.                         smoke[i].sy += 1.0f;
  3012.  
  3013.                         /* Rotate the smoke puff */
  3014.                         smoke[i].rot += 0.5f;
  3015.  
  3016.                         /* Move smoke puff according to it's movement type */
  3017.                         if( smoke[i].type == SMOKEANIM_RISE )
  3018.                         {
  3019.                                 smoke[i].y -= 1.0f;
  3020.                         }
  3021.  
  3022.                         /* Check for maximum size */
  3023.                         if( smoke[i].sx >= 64.0f || smoke[i].sx >= 64.0f )
  3024.                                 smoke[i].active = No;
  3025.  
  3026.                 }
  3027.                
  3028.                 i++;
  3029.         }
  3030. }
  3031.  
  3032. void draw_player_dragon()
  3033. {
  3034.         /* Update the dragon's position */
  3035. //      dragon.x += dragon.vx;
  3036. //      dragon.y += dragon.vy;
  3037.  
  3038.         static int flash = No;
  3039.  
  3040.         /* Draw the dragon sprite */
  3041.         if( !flash )
  3042.         {
  3043.                 enable_2d();
  3044.                 transparent_blend( TRUE );
  3045.                 set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3046.                 translate( dragon.x, dragon.y );
  3047.                 draw_quad( get_texture( "dragon1" ), 0.0f, 0.0f, dragon.width, dragon.height );
  3048.                 transparent_blend( FALSE );
  3049.                 disable_2d();
  3050.         }
  3051.  
  3052.         if( dragon.inv_t > 0 )
  3053.         {
  3054.                 dragon.inv_t--;
  3055.                 flash = !flash;
  3056.         }
  3057.         else
  3058.                 flash = No;
  3059. }
  3060.  
  3061. void draw_hud()
  3062. {
  3063.         char string[64];
  3064.  
  3065.         /* Enable 2D drawing with colour key enabled */
  3066.         enable_2d();
  3067.         transparent_blend( TRUE );
  3068.  
  3069.         /* draw the health bar */
  3070.         push_pos();
  3071.         set_colour( 0.0f, 1.0f, 0.0f, 0.5f );
  3072.         translate( 160.0f, 480.0f - 50.0f );
  3073.         draw_quad( 0, 10.0f, 0, (float) dragon.energy, 8.0f );
  3074.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3075.         draw_line( 10.0f, 0.0f, (float) dragon.max_energy + 10.0f, 0.0f );
  3076.         draw_line( 10.0f, 8.0f, (float) dragon.max_energy + 10.0f, 8.0f );
  3077.         draw_line( 10.0f, 0.0f, 10.0f, 8.0f );
  3078.         draw_line( (float) dragon.max_energy + 10.0f, 0.0f, (float) dragon.max_energy + 10.0f, 8.0f );
  3079.         pop_pos();
  3080.  
  3081.         /* display player's score and attack mode*/
  3082.         push_pos();
  3083.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3084. //      translate( 640.0f/4.0f, 0.0f );
  3085.         sprintf( string, "SCORE: %d", score );
  3086.         draw_text( &fonts[FONT_STEEL], 640.0f/4.0f, 0, string );
  3087.         draw_text( &fonts[FONT_BOLD], 330.0f, 0,
  3088.                 (dragon.attack_mode == 0) ? "FULL AUTO" : "HOMING" );
  3089.         pop_pos();
  3090.  
  3091.         /* draw the powerups obtained (crystals) */
  3092.         push_pos();
  3093.         transparent_blend( TRUE );
  3094.         translate( 165.0f, 480.0f - 38.0f );
  3095.  
  3096.         /* Special attack */
  3097.         if( dragon.powers[0] )
  3098.                 set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3099.         else
  3100.                 set_colour( 1.0f, 1.0f, 1.0f, .5f );
  3101.        
  3102.         draw_quad( get_texture( "diamond1" ), 0, 0, 32.0f, 32.0f );
  3103.  
  3104.         /* Overdrive */
  3105.         if( dragon.powers[1] )
  3106.                 set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3107.         else
  3108.                 set_colour( 1.0f, 1.0f, 1.0f, .5f );
  3109.  
  3110.         draw_quad( get_texture( "diamond2" ), 32.0f, 0, 32.0f, 32.0f );
  3111.  
  3112.         /* Barrier */
  3113.         if( dragon.powers[2] )
  3114.                 set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3115.         else
  3116.                 set_colour( 1.0f, 1.0f, 1.0f, .5f );
  3117.  
  3118.         draw_quad( get_texture( "diamond3" ), 64.0f, 0, 32.0f, 32.0f );
  3119.  
  3120.         pop_pos();
  3121.  
  3122.         /* Disable 2D drawing and colour key */
  3123.         transparent_blend( FALSE );
  3124.         disable_2d();
  3125. }
  3126.  
  3127. int draw_shogun3d_logo()
  3128. {
  3129.         static float a = 255.0f;
  3130.         static int timer = 0;
  3131.         int finished = 0;
  3132.  
  3133.         /* Enable 2D rendering */
  3134.         enable_2d();
  3135.  
  3136.         /* Draw the Shogun3D logo */
  3137.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3138.         draw_quad( get_texture( "shogun3d" ), 0.0f, 0.0f, 640.0f, 480.0f );
  3139.  
  3140.         /* Draw the transparent quad over it to simulate fading in/out */
  3141.         transparent_blend( TRUE );
  3142.         set_colour( 0.0f, 0.0f, 0.0f, a/255.0f );
  3143.         draw_quad( 0, 0.0f, 0.0f, 640.0f, 480.0f );
  3144.         transparent_blend( FALSE );
  3145.  
  3146.         /* Return to default colour (opaque white) */
  3147.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3148.  
  3149.         /* Disable 2D rendering */
  3150.         disable_2d();
  3151.  
  3152.         /* Update timing and alpha values */
  3153.         if( timer != 200 && a > 0.0f )
  3154.                 a -= 5.0f;
  3155.  
  3156.         if( a <= 0.0f && timer != 200 )
  3157.                 timer++;
  3158.  
  3159.         if( timer >= 200 /*&& a < 255.0f*/ )
  3160.                 a += 5.0f;
  3161.  
  3162.         if( timer >= 200 && a >= 255.0f )
  3163.         {
  3164.                 timer = 0;
  3165.                 finished = 1;
  3166.         }
  3167.  
  3168.         /* Return result */
  3169.         return finished;
  3170. }
  3171.  
  3172. int draw_purpose_disclaimer()
  3173. {
  3174.         static float a = 255.0f;
  3175.         static int timer = 0;
  3176.         int finished = 0;
  3177.  
  3178.         /* Enable 2D rendering */
  3179.         enable_2d();
  3180.  
  3181.         /* Draw black backdrop quad */
  3182.         set_colour( 0.0f, 0.0f, 0.0f, 1.0f );
  3183.         draw_quad( 0, 0.0f, 0.0f, 640.0f, 480.0f );
  3184.  
  3185.         /* Set base colour to white */
  3186.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3187.  
  3188.         /* Tell the whole world who I did this for and why =) */
  3189.         draw_text( &fonts[2], 75, 200, "This game is a labour of love!" );
  3190.         draw_text( &fonts[2], 75, 232, "        For Lady Mia..." );
  3191.  
  3192.         /* Draw some hearts to show her some love! */
  3193.         draw_quad( get_texture( "heart1" ), 50.0f, 200.0f, 32.0f, 32.0f );
  3194.         draw_quad( get_texture( "heart2" ), 560.0f, 200.0f, 32.0f, 32.0f );
  3195. //      draw_quad( get_texture( "heart" ), 180.0f, 232, 32.0f, 32.0f );
  3196. //      draw_quad( get_texture( "heart" ), 450.0f, 232, 32.0f, 32.0f );
  3197.  
  3198. //      draw_text( &fonts[3], 0, 10, "%" );
  3199. //      draw_text( &fonts[4], 0, 10, "LOVE YOU FOREVER!" );
  3200. //      set_colour( 1.0f, 1.0f, 0.0f, 1.0f );
  3201. //      draw_text( &fonts[5], 0, 10, "This is text..." );
  3202.  
  3203.         /* Draw the transparent quad over it to simulate fading in/out */
  3204. #if 1
  3205.         transparent_blend( TRUE );
  3206.         set_colour( 0.0f, 0.0f, 0.0f, a/255.0f );
  3207.         draw_quad( 0, 0.0f, 0.0f, 640.0f, 480.0f );
  3208.         transparent_blend( FALSE );
  3209. #endif
  3210.         /* Return to default colour (opaque white) */
  3211.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3212.  
  3213.         /* Disable 2D rendering */
  3214.         disable_2d();
  3215. #if 1
  3216.         /* Update timing and alpha values */
  3217.         if( timer != 200 && a > 0.0f )
  3218.                 a -= 5.0f;
  3219.  
  3220.         if( a <= 0.0f && timer != 200 )
  3221.                 timer++;
  3222.  
  3223.         if( timer >= 200 /*&& a < 255.0f*/ )
  3224.                 a += 5.0f;
  3225.  
  3226.         if( timer >= 200 && a >= 255.0f )
  3227.         {
  3228.                 timer = 0;
  3229.                 finished = 1;
  3230.         }
  3231. #endif
  3232.         /* Return result */
  3233.         return finished;
  3234. }
  3235.  
  3236.        
  3237. int draw_hero_intro()
  3238. {
  3239.         const float end_x = 320.0f-125.0f;
  3240.         const float end_y = 240.0f-160.0f;
  3241.         static struct Vector2 blur_v[5];
  3242.         static float a = 255.0f;
  3243.         static float blur_a[5] = { (255.0f), (255.0f/2.0f), (255.0f/3.0f), (255.0f/4.0f), (255.0f/5.0f) };
  3244.         static int timer = 0;
  3245.         int finished = 0;
  3246.         static int first = 1;
  3247.         int i = 4;
  3248.  
  3249.         if( first )
  3250.         {
  3251.                 play_sound_effect_static( &sfx[6], 0 );
  3252.  
  3253.                 blur_v[0].x = end_x-(20.0f*20.0f); blur_v[0].y = end_y-(20.0f*20.0f);
  3254.                 blur_v[1].x = end_x-(20.0f*22.0f), blur_v[1].y = end_y-(20.0f*22.0f);
  3255.                 blur_v[2].x = end_x-(20.0f*24.0f), blur_v[2].y = end_y-(20.0f*24.0f);
  3256.                 blur_v[3].x = end_x-(20.0f*26.0f), blur_v[3].y = end_y-(20.0f*26.0f);
  3257.                 blur_v[4].x = end_x-(20.0f*28.0f), blur_v[4].y = end_y-(20.0f*28.0f);
  3258.                 first = 0;
  3259.         }
  3260.  
  3261.         enable_2d();
  3262.  
  3263.         /* Draw white backdrop quad */
  3264.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3265.         draw_quad( 0, 0.0f, 0.0f, 640.0f, 480.0f );
  3266.  
  3267.         transparent_blend( TRUE );
  3268.  
  3269.         /* Draw the image of the hero */
  3270.         while( i != -1 )
  3271.         {
  3272.                 set_colour( 1.0f, 1.0f, 1.0f, (blur_a[i]/255.0f) );
  3273.                 draw_quad( get_texture( "hero" ), blur_v[i].x, blur_v[i].y, 250.0f, 320.0f );
  3274.  
  3275.                 if( blur_v[i].x < end_x )
  3276.                         blur_v[i].x += 10.0f;
  3277.                 if( blur_v[i].y < end_y )
  3278.                         blur_v[i].y += 10.0f;
  3279.  
  3280.                 i--;
  3281.         }
  3282.  
  3283.         /* Draw transparent foreground */
  3284.         set_colour( 1.0f, 1.0f, 1.0f, a/255.0f );
  3285.         draw_quad( 0, 0.0f, 0.0f, 640.0f, 480.0f );
  3286.  
  3287.         transparent_blend( FALSE );
  3288.  
  3289.         disable_2d();
  3290.  
  3291.         /*  */
  3292.         if( a > 0.0f && timer == 0 )
  3293.                 a -= 5.0f;
  3294.         if( a == 0.0f && timer != 50 )
  3295.                 timer++;
  3296.         if( timer >= 50 )
  3297.                 a += 5.0f;
  3298.         if( a >= 255.0f && timer >= 50 )
  3299.         {
  3300.                 timer = 0;
  3301.                 finished = 1;
  3302.                 wavestream_play(&bgm);
  3303.         }
  3304.  
  3305.         return finished;
  3306. }
  3307.  
  3308.  
  3309. int do_fade( int fade_in )
  3310. {
  3311.         int finished = No;
  3312.         extern float current_colour[4];
  3313.  
  3314.         /* Enable 2D rendering */
  3315.         enable_2d();
  3316.  
  3317.         if( fade_in )
  3318.         {
  3319.                 static float a = 255.0f;
  3320.  
  3321.                 transparent_blend(Yes);
  3322.                 set_colour( current_colour[0], current_colour[0], current_colour[0], a/255.0f );
  3323.                 draw_quad( 0, 160.0f, 0.0f, 320.0f, 480.0f );
  3324.                 transparent_blend(No);
  3325.  
  3326.                 a -= 5.0f;
  3327.  
  3328.                 if( a < 0.0f )
  3329.                 {
  3330.                         a = 255.0f;
  3331.                         finished = Yes;
  3332.                 }
  3333.         }
  3334.         else
  3335.         {
  3336.                 static float a = 0.0f;
  3337.  
  3338.                 transparent_blend(Yes);
  3339.                 set_colour( current_colour[0], current_colour[0], current_colour[0], a/255.0f );
  3340.                 draw_quad( 0, 160.0f, 0.0f, 320.0f, 480.0f );
  3341.                 transparent_blend(No);
  3342.  
  3343.                 a += 5.0f;
  3344.  
  3345.                 if( a > 255.0f )
  3346.                 {
  3347.                         a = 0.0f;
  3348.                         finished = Yes;
  3349.                 }
  3350.         }
  3351.  
  3352.         /* Disable 2D rendering */
  3353.         disable_2d();
  3354.  
  3355.         return finished;
  3356. }
  3357.  
  3358. int fade_out_bgm()
  3359. {
  3360.         int finished = No;
  3361.         static float volume = 1.0f;
  3362.  
  3363.         /* Continually decrease bgm volume until it reaches 0 */
  3364.  
  3365.         /* Are we done yet? */
  3366.         if( volume < 0.0f )
  3367.         {
  3368.                 /* Mark as finished */
  3369.                 finished = Yes;
  3370.                 volume = 1.0f;
  3371.  
  3372.                 /* Close the current track */
  3373.                 wavestream_close(&bgm);
  3374.  
  3375.                 /* Are we loading a new track? */
  3376.                 if( strcmp( "", bgm_next_track ) )
  3377.                 {
  3378.                         /* If so, open it and start playing */
  3379.                         wavestream_open(bgm_next_track, &bgm);
  3380.                         wavestream_play(&bgm);
  3381.                 }
  3382.                 else
  3383.                 {
  3384.                         /* If not, don't do a darn thing */
  3385.                 }
  3386.         }
  3387.         else
  3388.         {
  3389.                 wavestream_set_volume( &bgm, volume );
  3390.                 volume -= 0.01f;
  3391.         }
  3392.  
  3393.         return finished;
  3394. }
  3395.  
  3396. #if 0
  3397. /* Test code for target tracking */
  3398. void clamp_float( float* d, float min, float max )
  3399. {
  3400.         if( *d < min )
  3401.                 *d = min;
  3402.  
  3403.         if( *d > max )
  3404.                 *d = max;
  3405. }
  3406.  
  3407. void test_track()
  3408. {
  3409.         static struct Vector2 p = { 0.0f, 320.0f };
  3410.         static struct Vector2 v = { 0.0f, 0.0f };
  3411.  
  3412.         float angle_to_player = angle( p.x, p.y, dragon.x, dragon.y );
  3413.         float speed = 10.0f;
  3414.  
  3415.         v.x += cos(angle_to_player);
  3416.         v.y += sin(angle_to_player);
  3417.  
  3418.         clamp_float( &v.x, -speed, speed );
  3419.         clamp_float( &v.y, -speed, speed );
  3420.  
  3421.         p.x += v.x;
  3422.         p.y += v.y;
  3423.  
  3424.         enable_2d();
  3425.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3426.         transparent_blend(TRUE);
  3427.         draw_quad( get_texture("hblast2"), p.x+(106.0f/2.0f), p.y+(149.0f/2.0f), 32.0f, 32.0f );
  3428.         transparent_blend(FALSE);
  3429.         disable_2d();
  3430. }
  3431. #endif
  3432.  
  3433. void adjust_framerate()
  3434. {
  3435.         if( game_state == GAME_STATE_INGAME )
  3436.         {
  3437.                 if( get_spf() > 150 )
  3438.                         fps_limit = (int)(30.0f*((float)(game_speed/100.0f)));
  3439.                 else
  3440.                         fps_limit = (int)(60.0f*((float)(game_speed/100.0f)));;
  3441.         }
  3442.         else
  3443.         {
  3444.                 fps_limit = 60;
  3445.         }
  3446. }
  3447.  
  3448. void render()
  3449. {
  3450.         /* The background is displayed regardless of game state */
  3451.         draw_background();
  3452.  
  3453.         wavestream_update(&bgm);
  3454.  
  3455.         /* Input devices are updated regardless of game state */
  3456.         update_input_devices();
  3457.  
  3458.         switch( game_state )
  3459.         {
  3460.         case GAME_STATE_INTRO1:
  3461.                 if( draw_shogun3d_logo() )
  3462.                         game_state = GAME_STATE_INTRO2;
  3463.                 break;
  3464.  
  3465.         case GAME_STATE_INTRO2:
  3466.                 if( draw_purpose_disclaimer() )
  3467.                         game_state = GAME_STATE_INTRO3;
  3468.                 break;
  3469.  
  3470.         case GAME_STATE_INTRO3:
  3471.                 if( draw_hero_intro() )
  3472.                         game_state = GAME_STATE_MENU;
  3473.                 break;
  3474.  
  3475.         case GAME_STATE_MENU:
  3476.                 draw_menus();
  3477.                 break;
  3478.                
  3479.         case GAME_STATE_INGAME:
  3480.                 update_crosshair_position();
  3481.                 draw_environment();
  3482.                 draw_boss();
  3483.                 update_boss();
  3484.                 draw_enemies();
  3485.                 render_explosions();
  3486.                 draw_player_dragon();
  3487.                 draw_active_locks();
  3488.                 acquire_new_locks();
  3489.                 update_active_locks();
  3490.                 update_explosions();
  3491.                 draw_homing_blasts();
  3492.                 update_homing_blasts();
  3493.                 draw_fullautoblasts();
  3494.                 update_fullautoblasts();
  3495.                 check_homing_blasts_for_collisions();
  3496.                 check_fullauto_blasts_for_collisions();
  3497.                 draw_enemy_shoots();
  3498.                 update_enemy_shoots();
  3499.                 draw_smoke_puffs();
  3500.                 update_smoke_puffs();
  3501.                 draw_powerups();
  3502.                 update_powerups();
  3503.                 draw_gold_peices();
  3504.                 update_gold_peices();
  3505.                 update_guard_if_activated();    /* Update guard first */
  3506.                 draw_guard_if_activated();
  3507.                 draw_hud();
  3508.                 get_attack_mode_changes();
  3509.                 handle_mouse_input();
  3510.                 move_dragon();
  3511.                 check_for_special_input();
  3512.                 update_overdrive_if_active();
  3513.                 draw_crosshair();
  3514.                 /* Should be last */
  3515.                 draw_boundaries();
  3516. #if 0
  3517.                 test_track();
  3518. #endif
  3519.                 if( ingame_fade == 0 )  /* Fade out */
  3520.                 {
  3521.                         if( do_fade(No) )
  3522.                                 ingame_fade = -1;
  3523.                 }
  3524.                 if( ingame_fade == 1 )  /* Fade in */
  3525.                 {
  3526.                         if( do_fade(Yes) )
  3527.                                 ingame_fade = -1;
  3528.                 }
  3529.  
  3530.                 adjust_framerate();
  3531.                 break;
  3532.  
  3533.         case GAME_STATE_EXITING:
  3534.                 uninit_game();
  3535.                 PostQuitMessage(0);
  3536.                 break;
  3537.         }
  3538.        
  3539.         /* If we are transitioning to a new level... */
  3540.         if( bgm_fade )
  3541.         {
  3542.                 if( fade_out_bgm() )
  3543.                         bgm_fade = No;
  3544.         }
  3545.  
  3546.         /* Copy the screen to a texture */
  3547.         /*copy_scene_to_texture( &render_target, 640, 480 );
  3548.         transparent_blend(No);
  3549.         set_colour( 1.0f, 1.0f, 1.0f, 1.0f );
  3550.         enable_2d();
  3551.         draw_quad( render_target, 0, 0, 320.0f, 240.0f );
  3552.         disable_2d();*/
  3553.  
  3554.         /* Disable vsync when ingame */
  3555.         /*enable_vsync( (game_state != GAME_STATE_INGAME) );*/
  3556. }
clone this paste RAW Paste Data