/* gradientwars - Bullet Hell shooter with some (hopefully) pretty gradients

   By James Stanley

   No license - Use as you wish */

#include "main.h"

volatile int timer;
volatile int seconds;
int spawncount;
int gamemode;

void count(void) {
  timer++;
}

void secondcount(void) {
  seconds++;
}

/* Just see random noise? Try looking at the screen through a red filter ;) */
void draw_red_glasses(BITMAP *img, BITMAP *dest) {
  int x, y;
  int r, g, b, pix;
  static BITMAP *out;
  
  if(!out) out = create_bitmap(img->w, img->h);
  
  for(y = 0; y < img->h; y++) {
    for(x = 0; x < img->w; x++) {
      pix = mygetpixel(img, x, y);
      r = mygetr(pix);
      g = mygetg(pix);
      b = mygetb(pix);
      r = (r + g + b)/3;
      myputpixel(out, x, y, mymakecol(r, rand()%255, rand()%255));
    }
  }
  
  blit(out, dest, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}

void draw_edge_detected(BITMAP *img, BITMAP *dest) {
  static BITMAP *edges;
  int r, g, b, x, y, pix;
  
  if(!edges) edges = create_bitmap(img->w, img->h);
  
  for(y = 1; y < (img->h-1); y++) {
    for(x = 1; x < (img->w-1); x++) {
      pix = mygetpixel(img, x, y);
      r = mygetr(pix)*4;
      g = mygetg(pix)*4;
      b = mygetb(pix)*4;
      pix = mygetpixel(img, x-1, y);
      r -= mygetr(pix); g -= mygetg(pix); b -= mygetb(pix);
      pix = mygetpixel(img, x+1, y);
      r -= mygetr(pix); g -= mygetg(pix); b -= mygetb(pix);
      pix = mygetpixel(img, x, y-1);
      r -= mygetr(pix); g -= mygetg(pix); b -= mygetb(pix);
      pix = mygetpixel(img, x, y+1);
      r -= mygetr(pix); g -= mygetg(pix); b -= mygetb(pix);
      if(r < 0) r = 0;
      if(g < 0) g = 0;
      if(b < 0) b = 0;
      if(r > 255) r = 255;
      if(g > 255) g = 255;
      if(b > 255) b = 255;
      /*//Varied mode:
      myputpixel(edges, x, y, mymakecol(r, g, b));*/
      /*//Binary mode:
      if((r + g + b) > 100) myputpixel(edges, x, y, 0xffffffff);
      else myputpixel(edges, x, y, 0);*/
      //Greyscale varied mode:
      r = (r + g + b)/3;
      myputpixel(edges, x, y, mymakecol(r, r, r));
      /*//Greyscale varied mode with cut-off:
      r = (r + g + b)/3;
      if(r > 10) myputpixel(edges, x, y, mymakecol(r, r, r));
      else myputpixel(edges, x, y, 0);*/
      /*//Red glasses mode
      r = (r + g + b)/3;
      myputpixel(edges, x, y, makecol(r, rand()%255, rand()%255));*/
    }
  }
  
  blit(edges, dest, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}

int main(int argc, char **argv) {
  int i;
  int frames = 0, fps = 0;
  int loops = 0, lps = 0;
  int glow = 127, glowdir = 10;
  int menuopt = STARTGAME;
  char *menuitem[3] = { "Normal game", "Rocket game", "Exit" };
  int keyed;
  int powerupcount = 0;
  int oxs = 5, oys = 2;
  BITMAP *canvas;
  
  allegro_init();
  
  set_color_depth(COLOUR_DEPTH);
#ifdef GP2X
  set_gfx_mode(GFX_AUTODETECT, SCR_WIDTH, SCR_HEIGHT, 0, 0);
#else
  set_gfx_mode(GFX_AUTODETECT_WINDOWED, SCR_WIDTH, SCR_HEIGHT, 0, 0);
#endif
  
#ifdef DEBUG_MODE
  set_window_title("Gradient Wars (debug)");
#else
  set_window_title("Gradient Wars");
#endif
  
  canvas = create_bitmap(SCR_WIDTH, SCR_HEIGHT);
  
#ifndef GP2X
  install_keyboard();
#endif
  install_joystick(JOY_TYPE_AUTODETECT);
  
  install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
  
  LOCK_VARIABLE(timer);
  LOCK_FUNCTION(count);
  LOCK_VARIABLE(seconds);
  LOCK_FUNCTION(secondcount);
  
  install_int_ex(count, BPS_TO_TIMER(50));
  install_int(secondcount, 1000);
  
  load_images();
  load_sounds();
  load_highscore();

  init_colours();

  srand(time(0));
  
  init_noise(3);
  
  update_bg(1);
  update_player_img();
  
  while(1) {
    for(i = 0; i < timer; i++) {//Logic
      poll_joystick();
      loops++;
      if(seconds > 0) {
        //Frames per second
        fps = frames/seconds;
        frames = 0;
        //Loops per second
        lps = loops/seconds;
        loops = 0;
        seconds = 0;
      }
      
#ifndef NO_MUSIC
      //Update music
      if(voice_get_position(music_voice) == -1) {
        reallocate_voice(music_voice, music[rand()%TRACKS]);
        voice_start(music_voice);
      }
#endif
      
      update_texts();
      update_sparks();
      
      if(key[KEY_F1]) {
        if(!keyed) {
          draw_alg = (draw_alg + 1) % DRAW_ALGS;
          clear_to_color(bg, inv_col[draw_alg]);
          keyed = 1;
        }
      } else if(plives >= 0) keyed = 0;//Only reset keyed if in game mode
      
      if(plives >= 0) {//Game
        player_control();
        player_update();
        update_enemies();
        update_bullets();
        update_powerups();
        
        update_offset();
        
        //Spawn bad guys
        spawncount++;
        if(gamemode == NORMAL) {//No spawning in rocket-evasion mode
          if(spawncount > 50) {
            spawn_enemy(pscore);
            spawncount = 0;
          }
        } else pscore++;//Get point per loop in rocket game
        
        //Spawn powerups
        powerupcount++;
        if(gamemode == NORMAL) {//No spawning in rocket-evasion mode
          if((powerupcount > 80) && ((rand()%10) == 0)) {
            spawn_powerup(pscore);
            powerupcount = 0;
          }
        }
        
        if(plives < 0) {//We only just died now
          offsetx = 0;
          offsety = 0;
          save_highscore();
          display_text("GAME OVER", MENU_X+80, MENU_Y+80);
        }
        
        //Update dynamic images
        update_player_img();
        update_bg(0);
        
        if(gamemode == NORMAL) {
          if(pscore > bestscore) bestscore = pscore;
        } else {
          if(pscore > bestrocketscore) bestrocketscore = pscore;
        }
        
        if(key[KEY_ESC]) {
          offsetx = 0;
          offsety = 0;
          plives = -1;
          keyed = 1;
          update_bg(0);//Prevent the annoying bug where the picture looks shit
        }
      } else {//Menu////////////////////////////////////////
        if(rand()%20) {// != 0
          oxs += (rand()%5)-2;
        }
        if(rand()%20) {// != 0
          oys += (rand()%5)-2;
        }
        offsetx += oxs;
        offsety += oys;
        
        if(oxs > 5) oxs = 5;
        else if(oxs < -5) oxs = -5;
        if(oys > 5) oys = 5;
        else if(oys < -5) oys = -5;
        
        if(offsetx > 0) {
          offsetx = 0;
          oxs = -oxs;
        } else if(offsetx < -(WIDTH-SCR_WIDTH)) {
          offsetx = (WIDTH-SCR_WIDTH);
          oxs = -oxs;
        }
        
        if(offsety > 0) {
          offsety = 0;
          oys = -oys;
        } else if(offsety < -(HEIGHT-SCR_HEIGHT)) {
          offsety = (HEIGHT-SCR_HEIGHT);
          oys = -oys;
        }
        
        update_bg(1);
        
        if((rand()%20) == 0) {
          new_explosion(itofix(rand()%SCR_WIDTH), itofix(rand()%SCR_HEIGHT));
        }
        
        new_thrust(itofix(MENU_X+200), itofix(MENU_Y+(menuopt*32)+104), 0);
        
        glow += glowdir;
        if(glow > 200) glowdir = -10;
        if(glow < 32) glowdir = 10;
        if(key[KEY_DOWN] || joy[0].stick[0].axis[1].d2) {
          if(!keyed) {
            keyed = 1;
            menuopt++;
          }
        } else if(key[KEY_UP] || joy[0].stick[0].axis[1].d1) {
          if(!keyed) {
            keyed = 1;
            menuopt--;
          }
        } else if(key[KEY_ESC] || joy[0].button[1].b) {
          if(!keyed) return 0;
        } else if(key[KEY_ENTER] || joy[0].button[0].b) {
          if(!keyed) {
            switch(menuopt) {
              case STARTGAME:
                plives = 4; phealth = 40;
                px = itofix(WIDTH/2); py = itofix(HEIGHT/2);
                pxs = 0; pys = 0;
                pangle = 0; pthrust = 0;
                pscore = 0; pcurlevel = 0;
                pweapon = STANDARD;
                pweptime = 0;
#ifdef DEBUG_MODE
                if(argc > 1) pscore = atoi(argv[1]);
#endif
                kill_enemies(0);
                kill_powerups();
                del_all_bullets();
                gamemode = NORMAL;
                break;
              case ROCKETGAME:
                plives = 2; phealth = 40;
                px = itofix(WIDTH/2); py = itofix(HEIGHT/2);
                pxs = 0; pys = 0;
                pangle = 0; pthrust = 0;
                pscore = 0; pcurlevel = 0;
                pweapon = STANDARD;
                pweptime = 0;
#ifdef DEBUG_MODE
                if(argc > 1) pscore = atoi(argv[1]);
#endif
                kill_enemies(0);
                new_enemy(itofix(rand()%WIDTH), itofix(rand()%HEIGHT), 0, 0, itofix(rand()%255), ROCKET, 50);
                del_all_bullets();
                gamemode = ROCKETS;
                break;
              case QUITGAME:
                return 0;
                break;
            }
          }
        } else if(!key[KEY_F1]) keyed = 0;
        while(menuopt < 0) menuopt += 3;
        menuopt %= 3;
      }
    }
    timer = 0;
    
    //Graphics
    frames++;
    clear_bitmap(canvas);
    
    if(plives >= 0) {//Game
      draw_game(canvas, 0);
      masked_blit(hud, canvas, 0, 0, (SCR_WIDTH/2)-(320/2), (SCR_HEIGHT-240), 320, 240);
      textprintf_ex(canvas, numbers, (SCR_WIDTH/2)-(320/2)+230, (SCR_HEIGHT-240)+215, 0, -1, "%d", pscore);
      for(i = 0; i < (plives); i++) {
        draw_sprite(canvas, plainplayer, (SCR_WIDTH/2)-(320/2)+(i*26)+2, (SCR_HEIGHT-240)+215);
      }
      rotate_sprite(canvas, player, (SCR_WIDTH/2)-(320/2)+(i*26)+2, (SCR_HEIGHT-240)+215, pangle);
    } else {//Menu
      draw_game(canvas, 1);
      masked_blit(menu_bg, canvas, 0, 0, MENU_X, MENU_Y, SCR_WIDTH, SCR_HEIGHT);
      for(i = 0; i < 3; i++) {
        rectfill(canvas, MENU_X+12, MENU_Y+(i*32)+96, MENU_X+200, MENU_Y+(i*32)+112, (menuopt == i) ? mymakecol(0, 255-glow, glow) : mymakecol(127, 127, 127));
        if(menuopt == i) {
          rectfill(canvas, MENU_X+188-(glow/10), MENU_Y+(i*32)+100, MENU_X+196-(glow/10), MENU_Y+(i*32)+108, mymakecol(127, 127, 127));
        }
        textout_ex(canvas, font, menuitem[i], MENU_X+16, MENU_Y+(i*32)+100, 0, -1);
      }
      textprintf_ex(canvas, font, MENU_X+16, MENU_Y+196, 0, -1, "Last game: %d (%s)", pscore, (gamemode == NORMAL ? "normal" : "rocket"));
      textprintf_ex(canvas, font, MENU_X+16, MENU_Y+212, 0, -1, "Best normal game: %d", bestscore);
      textprintf_ex(canvas, font, MENU_X+16, MENU_Y+228, 0, -1, "Best rocket game: %d", bestrocketscore);
    }
    
    textprintf_ex(canvas, font, 8, 8, 0, mymakecol(255, 255, 255), "%d fps", fps);
    textprintf_ex(canvas, font, 8, 16, 0, mymakecol(255, 255, 255), "%d lps", lps);
    
    blit(canvas, screen, 0, 0, 0, 0, SCR_WIDTH, SCR_HEIGHT);
    //draw_edge_detected(canvas, screen);
    //draw_red_glasses(canvas, screen);
  }
  
  return 0;
} END_OF_MAIN()
