#include "Graphics.h"

#define PLAYER_Y_START 100
#define PLAYER_X_SPEED 10
#define MAX_NPCS 5
#define MAX_STARS 10
#define MAX_PROJECTILES 10

//#defene PROFILE(X) lastprofile = clock(); X; printf("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t%s %i\n", #X, (clock() - lastprofile))
#define PROFILE(X) X

enum sprite_e{player_ship, durno_ship, ship_trgt, durno_ship2, ship2_trgt, player_shipl,player_shipr,explode_start,explode_shp2,explode_shp3,explode_end,photon1,photon2,plasma1,plasma2};
char *sprites[] = {"player_ship","durno_ship","ship_trgt","durno_ship2","ship2_trgt","player_shipl","player_shipr","explode_shp1","explode_shp2","explode_shp3","explode_shp4","photon1","photon2","plasma1","plasma2"};

char hudbuffer[63];

struct EntityLocation_s {
  short signed int X,Y;
};

enum npctype_e{bigdurno, littledurno,maxnpctype};

struct NPC_s {
  struct EntityLocation_s location;
  enum sprite_e idlesprite;
  enum sprite_e sprite;
  enum sprite_e weaponspritestart;
  enum sprite_e weaponspriteend;
  enum npctype_e npctype;
  struct EntityLocation_s velocity;
  int health;
  struct EntityLocation_s hitbox_bl;
  struct EntityLocation_s hitbox_tr;
  int collideforce;
  int collidable;
  int explodenextframe;
  int nextfire;
  int fireinterval;
  int firewidth;
};

struct Star_s {
  struct EntityLocation_s location;
  unsigned char length;
};

struct Player_s {
  struct EntityLocation_s location;
  enum sprite_e idlesprite;
  enum sprite_e sprite;
  unsigned char velocity;
  int nextidlesprite;
  int shields;
  int nextshieldheal;
  int integrity;
  int remainingdistance;
  struct EntityLocation_s hitbox_bl;
  struct EntityLocation_s hitbox_tr;
  struct EntityLocation_s phaser1;
  struct EntityLocation_s phaser2;
  int targetleft;
  int targetright;
  short int firingleft;
  short int firingright;
  int phaserdamage;
};

struct Projectile_s {
  struct EntityLocation_s location;
  enum sprite_e sprite;
  enum sprite_e spritestart;
  enum sprite_e spriteend;
  struct EntityLocation_s velocity;
  int collidable;
  int nextframe;
  short int active;
  int damage;
};

struct Star_s Stars[MAX_STARS];
struct NPC_s NPCS[MAX_NPCS];
struct Projectile_s Projectiles[MAX_PROJECTILES];
struct Player_s Player;

extern void game_respawn_npc(int id);
extern int tick;
extern int lasttick;

enum debugs_e{dbbase,dbhitbox,dbweapons,dbinput,dbperformance,dbnpcs,dbprojectiles,dbmax};
int debugs[dbmax];

enum colour_e{lcars_black,lcars_violet1,debugpink,stargrey,debuggreen,phaserorange1,phaserorange2};
int colours[] = {0x11111100,0xc4727200,0xcc00ff00,0x66666600,0x00ff0000,0x0053ff00,0x00d5ff00};

void game_spawn_projectile(int id, int Px, int Py, int Vx, int Vy, enum sprite_e spritestart, enum sprite_e spriteend, int damage)
{
  int i;
  
  if(id < 0)
  {
    for(i = 0; i < MAX_PROJECTILES; i++)
    {
        if(Projectiles[i].active == 0)
          id = i;
    }
  }

  // If no velocity X specified we're targetting the player
  if(Vx == 0)
  {
    int V;
    int Xdistance = abs((Player.location.X + (Player.hitbox_tr.X/2)) - Px);
    int Ydistance = abs((Player.location.Y + (Player.hitbox_tr.Y/2)) - Py);
    int distance = sqrt((Xdistance^2) + (Ydistance^2));
    V = Vy;
    Vx = Xdistance / (distance / Vy);
    Vy = Ydistance / (distance / Vy);

    if(Player.location.X > Px)
      Vx = 0 - Vx;
  }

  // If it's too close to horizontal you can't dodge
  if(Py < (Player.location.X + 100))
    id = -1;
  
  //If no free IDs then we go without
  if(id >= 0)
  {
    Projectiles[id].location.X = Px;
    Projectiles[id].location.Y = Py;
    Projectiles[id].velocity.X = Vx;
    Projectiles[id].velocity.Y = Vy;
    Projectiles[id].active = 1;
    Projectiles[id].sprite = spritestart;
    Projectiles[id].spritestart = spritestart;
    Projectiles[id].spriteend = spriteend;
    Projectiles[id].nextframe = tick + 10;
    Projectiles[id].damage = damage;
    Projectiles[id].collidable = 1;
  }

}

void game_draw_player()
{
  draw_sprite(sprites[Player.sprite], Player.location.X, Player.location.Y);

  if(debugs[dbhitbox])
  {
    graphics_colour(colours[debugpink]);

    // Bounding box debug
    draw_rectangle(
      Player.location.X + Player.hitbox_bl.X,
      Player.location.Y + Player.hitbox_bl.Y,
      Player.location.X + Player.hitbox_tr.X,
      Player.location.Y + Player.hitbox_tr.Y
    );
  }

  if((Player.firingleft) && (Player.targetleft >= 0))
  {
    graphics_colour(colours[phaserorange1]);
    draw_line(
      Player.location.X + Player.phaser1.X,
      Player.location.Y + Player.phaser1.Y,
      NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2),
      NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
    );
    graphics_colour(colours[phaserorange2]);
    draw_dotted_line(
      Player.location.X + Player.phaser1.X + 1,
      Player.location.Y + Player.phaser1.Y,
      NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2) + 1,
      NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
    );
    draw_dotted_line(
      Player.location.X + Player.phaser1.X - 1,
      Player.location.Y + Player.phaser1.Y,
      NPCS[Player.targetleft].location.X + ((NPCS[Player.targetleft].hitbox_bl.X + NPCS[Player.targetleft].hitbox_tr.X)/2) - 1,
      NPCS[Player.targetleft].location.Y + NPCS[Player.targetleft].hitbox_bl.Y
    );
  }

  if((Player.firingright) && (Player.targetright >= 0))
  {
    graphics_colour(colours[phaserorange1]);
    draw_line(
      Player.location.X + Player.phaser2.X,
      Player.location.Y + Player.phaser2.Y,
      NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2),
      NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
    );
    graphics_colour(colours[phaserorange2]);
    draw_dotted_line(
      Player.location.X + Player.phaser2.X + 1,
      Player.location.Y + Player.phaser2.Y,
      NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2) + 1,
      NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
    );
    draw_dotted_line(
      Player.location.X + Player.phaser2.X - 1,
      Player.location.Y + Player.phaser2.Y,
      NPCS[Player.targetright].location.X + ((NPCS[Player.targetright].hitbox_bl.X + NPCS[Player.targetright].hitbox_tr.X)/2) - 1,
      NPCS[Player.targetright].location.Y + NPCS[Player.targetright].hitbox_bl.Y
    );
  }

  if(debugs[dbweapons])
  {
    graphics_colour(colours[debuggreen]);

    // Draw phaser banks
    draw_line(
      Player.location.X + Player.phaser1.X,
      Player.location.Y + Player.phaser1.Y -5,
      Player.location.X + Player.phaser1.X,
      Player.location.Y + Player.phaser1.Y + 5
    );
    draw_line(
      Player.location.X + Player.phaser1.X -5,
      Player.location.Y + Player.phaser1.Y,
      Player.location.X + Player.phaser1.X +5,
      Player.location.Y + Player.phaser1.Y 
    );
    draw_line(
      Player.location.X + Player.phaser2.X,
      Player.location.Y + Player.phaser2.Y -5,
      Player.location.X + Player.phaser2.X,
      Player.location.Y + Player.phaser2.Y + 5
    );
    draw_line(
      Player.location.X + Player.phaser2.X -5,
      Player.location.Y + Player.phaser2.Y,
      Player.location.X + Player.phaser2.X +5,
      Player.location.Y + Player.phaser2.Y 
    );
  }
}

void game_draw_npcs()
{
  int i;
  for(i = 0; i < MAX_NPCS; i++)
  {
    // Don't bother if they are off the screen
    if(NPCS[i].location.Y < DISPLAY_Y)
    {
      draw_sprite(sprites[NPCS[i].sprite], NPCS[i].location.X, NPCS[i].location.Y);

      // Next sprite up in index is the appropriate target icon
      if(Player.targetleft == i)
        draw_sprite(sprites[NPCS[i].sprite + 1], NPCS[i].location.X, NPCS[i].location.Y);
      if(Player.targetright == i)
        draw_sprite(sprites[NPCS[i].sprite + 1], NPCS[i].location.X, NPCS[i].location.Y);

      if(tick > NPCS[i].explodenextframe)
      {
        if((NPCS[i].sprite >= explode_start) && (NPCS[i].sprite <= explode_end))
        {
          NPCS[i].sprite++;
          if(NPCS[i].sprite > explode_end)
            game_respawn_npc(i);
        }
        NPCS[i].explodenextframe = tick + 4;
      }
      
      if(debugs[dbhitbox])
      {
        graphics_colour(colours[debugpink]);

        // Bounding box debug
        draw_rectangle(
          NPCS[i].location.X + NPCS[i].hitbox_bl.X,
          NPCS[i].location.Y + NPCS[i].hitbox_bl.Y,
          NPCS[i].location.X + NPCS[i].hitbox_tr.X,
          NPCS[i].location.Y + NPCS[i].hitbox_tr.Y
        );
      }
    }
  }
}

void game_draw_projectiles()
{
  int i;
  for(i = 0; i < MAX_PROJECTILES; i++)
  {
    if(Projectiles[i].active == 0)
      continue;

    draw_sprite(sprites[Projectiles[i].sprite], Projectiles[i].location.X,Projectiles[i].location.Y);
    Projectiles[i].sprite++;
    if(Projectiles[i].sprite > Projectiles[i].spriteend)
      Projectiles[i].sprite = Projectiles[i].spritestart;
  }
}

void game_draw_stars()
{
  unsigned char i;
  graphics_colour(colours[stargrey]);
  for(i = 0; i < MAX_STARS; i++)
  {
    draw_line(Stars[i].location.X,Stars[i].location.Y,Stars[i].location.X,Stars[i].location.Y+Stars[i].length);
  }
}

void game_setup_player()
{
  Player.location.X = DISPLAY_X/2;
  Player.location.Y = PLAYER_Y_START;
  Player.sprite = player_ship;
  Player.idlesprite = player_ship;
  Player.velocity = 100;
  Player.shields = 100;
  Player.integrity = 100;
  Player.remainingdistance = 1500000;
  Player.hitbox_bl.X = 0;
  Player.hitbox_bl.Y = 0;
  Player.hitbox_tr.X = 60;
  Player.hitbox_tr.Y = 81;
  Player.phaser1.X = 20;
  Player.phaser1.Y = 75;
  Player.phaser2.X = 41;
  Player.phaser2.Y = 75;
  Player.targetleft = -1;
  Player.targetright = -1;
  Player.firingleft = 0;
  Player.firingright = 0;
  Player.phaserdamage = 10;
}

void game_tick_stars()
{
  int i;
  for(i = 0; i < MAX_STARS; i++)
  {
    Stars[i].location.Y -= (tick - lasttick) * 4;
    if((Stars[i].location.Y + Stars[i].length) <= 0)
    {
      Stars[i].length = 20 + (rand() % 10);
      Stars[i].location.X = rand() % DISPLAY_X;
      Stars[i].location.Y = DISPLAY_Y + Stars[i].length;
    }
  }
}

void game_setup_stars()
{
  int i;
  for(i = 0; i < MAX_STARS; i++)
  {
    Stars[i].length = 20 + (rand() % 10);
    Stars[i].location.X = rand() % DISPLAY_X;
    Stars[i].location.Y = rand() % DISPLAY_Y;
  }
}

void game_setup_input()
{
  /*
    inreg.r[0] = 4;
  inreg.r[1] = 1;
  _kernel_swi(OS_Byte,&inreg,&outreg);
  */
}

void game_respawn_npc(int id)
{
  NPCS[id].location.X = rand() % DISPLAY_X;
  NPCS[id].location.Y = DISPLAY_Y + (rand() % (DISPLAY_Y/2));
  if((rand() % 10) > 3)
    NPCS[id].npctype = littledurno;
  else
    NPCS[id].npctype = bigdurno;
  NPCS[id].collidable = 1;
  NPCS[id].nextfire = tick + (rand() % 100);
    switch(NPCS[id].npctype)
    {
      case bigdurno:
        NPCS[id].idlesprite = durno_ship;
        NPCS[id].sprite = durno_ship;
        NPCS[id].velocity.X = 0;
        NPCS[id].velocity.Y = (rand() % 3) + 1;
        NPCS[id].health = 1000;
        NPCS[id].hitbox_bl.X = 0;
        NPCS[id].hitbox_bl.Y = 0;
        NPCS[id].hitbox_tr.X = 48;
        NPCS[id].hitbox_tr.Y = 74;
        NPCS[id].collideforce = 1000;
        NPCS[id].weaponspritestart = photon1;
        NPCS[id].weaponspriteend = photon2;
        NPCS[id].fireinterval = 200;
        NPCS[id].firewidth = 400;
        break;
      case littledurno:
        NPCS[id].idlesprite = durno_ship2;
        NPCS[id].sprite = durno_ship2;
        NPCS[id].velocity.X = (rand() % 1) - 2;
        NPCS[id].velocity.Y = (rand() % 2) + 3;
        NPCS[id].health = 300;
        NPCS[id].hitbox_bl.X = 0;
        NPCS[id].hitbox_bl.Y = 0;
        NPCS[id].hitbox_tr.X = 38;
        NPCS[id].hitbox_tr.Y = 56;
        NPCS[id].collideforce = 50;
        NPCS[id].weaponspritestart = plasma1;
        NPCS[id].weaponspriteend = plasma2;
        NPCS[id].fireinterval = 80;
        NPCS[id].firewidth = 60;
        break;
    };
}

void game_setup_npcs()
{
  int i;
  for(i = 0; i < MAX_NPCS; i++)
  {
    game_respawn_npc(i);
  }
}

void game_tick_npcs()
{
  int i;
  for(i = 0; i < MAX_NPCS; i++)
  {
    NPCS[i].location.Y -= (tick - lasttick) * NPCS[i].velocity.Y;
    NPCS[i].location.X -= (tick - lasttick) * NPCS[i].velocity.X;

    if(NPCS[i].npctype == littledurno)
    {
      if(NPCS[i].location.Y > (Player.location.Y + 500))
      {
        if(abs(NPCS[i].location.X - Player.location.X) > 100)
        {
          if(NPCS[i].location.X < Player.location.X)
            NPCS[i].velocity.X = 0 - abs(NPCS[i].velocity.X);
          else
            NPCS[i].velocity.X = abs(NPCS[i].velocity.X);
        }
      }else{
        if(NPCS[i].velocity.X > 0)
         NPCS[i].velocity.X = 1;
        else
         NPCS[i].velocity.X = -1;
      }
    }

    if(NPCS[i].location.Y + NPCS[i].hitbox_tr.Y <= 0)
      game_respawn_npc(i);
    
    if((NPCS[i].location.X + NPCS[i].hitbox_tr.X) > DISPLAY_X)
      game_respawn_npc(i);
    
    if((NPCS[i].location.X + NPCS[i].hitbox_bl.X) < 0)
      game_respawn_npc(i);

    if(tick > NPCS[i].nextfire)
    {
      // Dont fire if off screen
      if((NPCS[i].location.Y < DISPLAY_Y))
      {
        if((NPCS[i].firewidth == -1) || (abs(Player.location.X - NPCS[i].location.X) < NPCS[i].firewidth))
        {
          if(NPCS[i].weaponspritestart == photon1)
            game_spawn_projectile(-1,NPCS[i].location.X, NPCS[i].location.Y, 0, 10, NPCS[i].weaponspritestart, NPCS[i].weaponspriteend, 60);
          else
            game_spawn_projectile(-1,NPCS[i].location.X, NPCS[i].location.Y, 0, 10, NPCS[i].weaponspritestart, NPCS[i].weaponspriteend, 20);
          NPCS[i].nextfire = tick + NPCS[i].fireinterval;
        }
      }
    }

    if(NPCS[i].health <= 0)
    {
      if(NPCS[i].sprite == NPCS[i].idlesprite)
      {
        NPCS[i].collidable = 0;
        NPCS[i].sprite = explode_start;
        NPCS[i].explodenextframe = tick + 4;
        sound_play(1,-5,0,100);
        sound_play(3,-15,0,1000);
        sound_play(2,-10,1,100);
      }
    }
  }
}

void game_draw_debugmenu()
{
/*  int i;
  if(debugs[dbbase])
  {
    font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
    draw_text("Debug List",DISPLAY_X-200,DISPLAY_Y-40,font[sys_12_8]);
    font_colour(colours[debugs[dbhitbox]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("1: hitbox",DISPLAY_X-200,DISPLAY_Y-60,font[sys_12_8]);
    font_colour(colours[debugs[dbweapons]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("2: weapons",DISPLAY_X-200,DISPLAY_Y-80,font[sys_12_8]);
    font_colour(colours[debugs[dbinput]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("3: input",DISPLAY_X-200,DISPLAY_Y-100,font[sys_12_8]);
    font_colour(colours[debugs[dbperformance]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("4: performance",DISPLAY_X-200,DISPLAY_Y-120,font[sys_12_8]);
    font_colour(colours[debugs[dbnpcs]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("5: NPCs",DISPLAY_X-200,DISPLAY_Y-140,font[sys_12_8]);
    font_colour(colours[debugs[dbprojectiles]?debugpink:stargrey],colours[lcars_black],font[sys_12_8]);
    draw_text("6: Projectiles",DISPLAY_X-200,DISPLAY_Y-160,font[sys_12_8]);
  }

  if(debugs[dbperformance])
  {
    font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
    sprintf(hudbuffer,"CPF: %i",(tick-lasttick));
    draw_text(hudbuffer,DISPLAY_X-500,DISPLAY_Y-60,font[sys_12_8]);
  }

  if(debugs[dbnpcs])
  {
    font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
    for(i = 0; i < MAX_NPCS; i++)
    {
      sprintf(hudbuffer,"NPCS[%i] %i%i,%i %i,%i %i",i,NPCS[i].health,NPCS[i].velocity.X,NPCS[i].velocity.Y,NPCS[i].location.X,NPCS[i].location.Y);
      draw_text(hudbuffer,DISPLAY_X-800,DISPLAY_Y-60-(i * 20),font[sys_12_8]);
    }
  }

  if(debugs[dbprojectiles])
  {
    font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
    for(i = 0; i < MAX_PROJECTILES; i++)
    {
      sprintf(hudbuffer,"Projectiles[%i] %i %i,%i %i,%i",i,Projectiles[i].active,Projectiles[i].velocity.X,Projectiles[i].velocity.Y,Projectiles[i].location.X,Projectiles[i].location.Y);
      draw_text(hudbuffer,DISPLAY_X-800,DISPLAY_Y-60-(i * 20),font[sys_12_8]);
    }
  }*/
}

void game_tick_collider()
{
  int i;
  for(i = 0; i < MAX_NPCS; i++)
  {
    if(!NPCS[i].collidable)
      continue;
    // Excuse this formatting
    if(
      game_hitbox_collide(
        (Player.location.X + Player.hitbox_bl.X),(Player.location.Y + Player.hitbox_bl.Y),
        (Player.hitbox_tr.X - Player.hitbox_bl.X),(Player.hitbox_tr.Y - Player.hitbox_bl.Y),
        (NPCS[i].location.X + NPCS[i].hitbox_bl.X),(NPCS[i].location.Y + NPCS[i].hitbox_bl.Y),
        (NPCS[i].hitbox_tr.X - NPCS[i].hitbox_bl.X),(NPCS[i].hitbox_tr.Y - NPCS[i].hitbox_bl.Y)
      )
    )
    {

      /*if(debugs[dbhitbox])
      {
        font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
        sprintf(hudbuffer,"NPCS[%i] hits player",i,NPCS[i].location.X,NPCS[i].location.Y);
        draw_text(hudbuffer,DISPLAY_X-900,DISPLAY_Y-260-(i * 20),font[sys_12_8]);
      }*/

      NPCS[i].health -= 300;
      NPCS[i].collidable = 0;
      NPCS[i].velocity.Y = NPCS[i].velocity.Y / 2;
      NPCS[i].velocity.X = NPCS[i].velocity.X * 4;

      Player.shields -= NPCS[i].collideforce;
      if(Player.shields < 0)
      {
        Player.integrity += Player.shields;
        Player.shields = 0;
      }
    }
  }

  for(i = 0; i < MAX_PROJECTILES; i++)
  {
    if(!Projectiles[i].active)
      continue;
    if(!Projectiles[i].collidable)
      continue;
    // Excuse this formatting
    if(
      game_hitbox_collide(
        (Player.location.X + Player.hitbox_bl.X),(Player.location.Y + Player.hitbox_bl.Y),
        (Player.hitbox_tr.X - Player.hitbox_bl.X),(Player.hitbox_tr.Y - Player.hitbox_bl.Y),
        Projectiles[i].location.X,Projectiles[i].location.Y,
        10,10
      )
    )
    {
      sound_play(2,-5, 20,1);
      Projectiles[i].active = 0;
      Player.shields -= Projectiles[i].damage;
      if(Player.shields < 0)
      {
        Player.integrity += Player.shields;
        Player.shields = 0;
      }
    }
  }
}

void game_tick_player_targets()
{
  int i;
  int NoseX = Player.location.X + Player.hitbox_bl.X + (Player.hitbox_tr.X/2);
  int NoseXLeft = Player.location.X + Player.hitbox_bl.X;
  int NoseXRight = Player.location.X + Player.hitbox_bl.X  + Player.hitbox_tr.X;
  int NoseY = Player.location.Y + + Player.hitbox_bl.Y  + Player.hitbox_tr.Y;
  int LeftDistance = 1000;
  int RightDistance = 1000;
  int LeftCornerX, LeftCornerY, RightCornerX,DistanceX,DistanceY;
  Player.targetleft = -1;
  Player.targetright = -1;

  for(i = 0; i < MAX_NPCS; i++)
  {
    if(!NPCS[i].collidable)
      continue;
    if(NPCS[i].location.Y > (DISPLAY_Y-50))
      continue;
    LeftCornerX = NPCS[i].location.X + NPCS[i].hitbox_bl.X;
    LeftCornerY = NPCS[i].location.Y + NPCS[i].hitbox_bl.Y;
    RightCornerX = NPCS[i].location.X + NPCS[i].hitbox_tr.X;

    if(LeftCornerY > NoseY)
    {
      DistanceY = LeftCornerY - NoseY;
      DistanceX = abs(NoseX - ((LeftCornerX + RightCornerX) / 2));

      if((DistanceY/5) > DistanceX)
      {
        if((NoseXRight - ((LeftCornerX + RightCornerX) / 2)) > 0)
        {
          if(DistanceY < LeftDistance)
          {
            LeftDistance = DistanceY;
            Player.targetleft = i;
          }
        }
        if((NoseXLeft - ((LeftCornerX + RightCornerX) / 2)) < 0)
        {
          if(DistanceY < RightDistance)
          {
            RightDistance = DistanceY;
            Player.targetright = i;
          }
        }
      }
    }
  }

}

void game_tick_projectiles()
{
  int i;
  for(i = 0; i < MAX_PROJECTILES; i++)
  {
    if(!Projectiles[i].active)
      continue;

    if(tick > Projectiles[i].nextframe)
    {
      if((Projectiles[i].sprite >= photon1) && (Projectiles[i].sprite <= photon2))
      {
        Projectiles[i].sprite++;
        if(Projectiles[i].sprite > photon2)
          Projectiles[i].sprite = photon1;
      }
      Projectiles[i].nextframe = tick + 10;
    }


    Projectiles[i].location.Y -= (tick - lasttick) * Projectiles[i].velocity.Y;
    Projectiles[i].location.X -= (tick - lasttick) * Projectiles[i].velocity.X;

    if((Projectiles[i].location.Y) <= 0)
    {
      Projectiles[i].active = 0;
    }
  }
}



void game_tick_input()
{
  if(debugs[dbbase])
  {
    // 1
    if(input_readkey(17))
      debugs[dbinput] = 1;
    // 2
    if(input_readkey(48))
      debugs[dbhitbox] = 1;
    // 3
    if(input_readkey(49))
      debugs[dbweapons] = 1;
    // 4
    if(input_readkey(18))
      debugs[dbperformance] = 1;
    // 5
    if(input_readkey(19))
      debugs[dbnpcs] = 1;
    // 6
    if(input_readkey(24))
      debugs[dbprojectiles] = 1;
  }
  
  /*if(debugs[dbinput])
  {
    font_colour(colours[debuggreen],colours[lcars_black],font[sys_12_8]);
    sprintf(hudbuffer,"Keycode: %i",input_readanykey());
    draw_text(hudbuffer,DISPLAY_X-500,DISPLAY_Y-40,font[sys_12_8]);
  }*/

  // Q
  if(input_readkey(16))
    debugs[dbbase] = 1;

  if(tick > Player.nextidlesprite)
    Player.sprite = Player.idlesprite;

  // Right arrow
  if(input_readkey(121))
  {
    Player.location.X += PLAYER_X_SPEED * (tick - lasttick);
    Player.sprite = player_shipr;
    Player.nextidlesprite = tick + 15;
    if((Player.location.X + Player.hitbox_tr.X) > DISPLAY_X)
    {
      Player.location.X = DISPLAY_X - Player.hitbox_tr.X;
    }
  }

  // Left arrow
  if(input_readkey(25))
  {
    Player.location.X -= PLAYER_X_SPEED * (tick - lasttick);
    Player.sprite = player_shipl;
    Player.nextidlesprite = tick + 15;
    if((Player.location.X + Player.hitbox_bl.X) < 0)
    {
      Player.location.X = 0 - Player.hitbox_bl.X;
    }
  }

  // Space
  if(input_readkey(98))
  {
    Player.firingleft = 1;
    Player.firingright = 1;
    Player.nextshieldheal = tick + 100;
  }else{
    Player.firingleft = 0;
    Player.firingright = 0;
  }
}

void game_setup_audio()
{
  sound_voices(4);

  sound_set_voice(1,"WaveSynth-Beep");
  sound_set_voice(2,"Percussion-Noise");
  sound_set_voice(3,"Percussion-Soft");
  sound_set_voice(4,"Percussion-Noise");
}

void game_draw_hud()
{
  draw_sprite("lcars",4,DISPLAY_Y-164);
  draw_sprite("pointer",141+(Player.shields*2),DISPLAY_Y - 164 + 84);
  draw_sprite("pointer",141+(Player.integrity*2),DISPLAY_Y - 164 + 44);
  draw_sprite("pointer",141+(Player.remainingdistance/7500),DISPLAY_Y - 164 + 4);
}

void game1_setup()
{
  game_setup_input();
  game_setup_audio();
  game_setup_stars();
  game_setup_player();
  game_setup_npcs();
  tick = clock();
}

void game_tick_player()
{
  Player.remainingdistance -= Player.velocity * (tick - lasttick);

  if(Player.shields < 100)
  {
    if(tick > Player.nextshieldheal)
    {
      Player.shields += 1;
      Player.nextshieldheal = tick + 10;
    }
  }

  if((Player.firingleft) && (Player.targetleft >= 0))
  {
    NPCS[Player.targetleft].health -= (tick - lasttick) * Player.phaserdamage;
  }

  if((Player.firingright) && (Player.targetright >= 0))
  {
    NPCS[Player.targetright].health -= (tick - lasttick) * Player.phaserdamage;
  }
}

void game1_death()
{
  int currentstart = 0;
  int introframe = 0;
  sound_voices(4);

  sound_set_voice(1,"WaveSynth-Beep");
  sound_set_voice(2,"WaveSynth-Beep");
  sound_set_voice(3,"WaveSynth-Beep");
  sound_set_voice(4,"WaveSynth-Beep");
  sound_composition_init();
  
  currentstart += 100;
  sound_composition_element_add(currentstart,1,sound_note("D2"),150);
  currentstart += 100;
  sound_composition_element_add(currentstart,2,sound_note("G2"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,3,sound_note("B3"),75);
  currentstart += 40;
  sound_composition_element_add(currentstart,4,sound_note("G2"),75);
  currentstart += 50;
  sound_composition_element_add(currentstart,2,sound_note("B3"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("A3"),100);
  currentstart += 100;
  sound_composition_element_add(currentstart,3,sound_note("G2"),150);
  currentstart += 150;
  sound_composition_element_add(currentstart,2,sound_note("E2"),100);
  currentstart += 100;
  sound_composition_element_add(currentstart,1,sound_note("D2"),150);
  currentstart += 150;
  sound_composition_element_add(currentstart,3,sound_note("D2"),150);
  currentstart += 100;
  sound_composition_element_add(currentstart,4,sound_note("G2"),150);
  currentstart += 150;
  sound_composition_element_add(currentstart,1,sound_note("B3"),75);
  currentstart += 40;
  sound_composition_element_add(currentstart,2,sound_note("G2"),75);
  currentstart += 40;
  sound_composition_element_add(currentstart,3,sound_note("B3"),150);
  currentstart += 150;
  sound_composition_element_add(currentstart,4,sound_note("A3"),130);
  currentstart += 100;
  sound_composition_element_add(currentstart,1,sound_note("G2"),200);
  currentstart += 300;
  tick = clock();

  sound_composition_start(clock());

  draw_sprite("spacebar",(DISPLAY_X/2)-106,50);
  draw_sprite("kia",(DISPLAY_X/2)-300,500);

  screen_flipbuffer();

  while(sound_composition_incomplete())
  {
    sound_composition_tick(clock());

      if(clock() > (tick + 200))
      {
        if(input_readkey(98))
          sound_composition_stop();
      }
  }
}


int game1_tick()
{
  lasttick = tick;
  tick = clock();

  screen_flipbuffer();
  screen_clear();

  if(Player.integrity > 0)
  {
    PROFILE(game_tick_stars());
    PROFILE(game_tick_input());
    PROFILE(game_tick_player());
    PROFILE(game_tick_npcs());
    PROFILE(game_tick_collider());
    PROFILE(game_tick_player_targets());
    PROFILE(game_tick_npcs());
    PROFILE(game_tick_projectiles());
    PROFILE(game_draw_stars());
    PROFILE(game_draw_player());
    PROFILE(game_draw_npcs());
    PROFILE(game_draw_projectiles());

    PROFILE(game_draw_hud());
    PROFILE(game_draw_debugmenu());
    return 0;
  }else{
    screen_flipbuffer();
    screen_clear();
    game1_death();
    return 1;
  }
  

}
