// Brian Kumanchik
// Started 05-25-22
// My Invader Demo, for Bangle.js 2, written JavaScript - using Espruino Web IDE


// note: resolution is 176x176


// to do:
//   upload to official app page
//   make invader clock



// - variables -----------------------------------------
var fgCol = g.theme.fg;
// invader variables
var inv_x             = 77;
var inv_y             = 20;
var i_anim_delay      = 10;     // invader animation (and move) delay
var inv_frame         = 1;      // invader start animation frame
var ix_speed          = 6;      // march speed
var i_dir             = 1;      // 1 = right, 0 = left
var been_hit          = false;  // invader hit state
// - shoot variables
var inv_shot_x        = -32;
var inv_shot_y        = -32;
var inv_fire_pause    = 30;
var inv_fired         = false;  // invader fired state
// - explode variables
var been_hit          = false;  // invader hit state
//var bx                = -32;    // blast x
//var by                = -32;    // blast y
var blast_delay       = 15;     // invader blast delay - pause after explosion
var boom_play         = false;

// turret variables
var tur_x               = 77;
var tur_y               = 148;
var shot_fired          = false; // turret fired state
var sx                  = -20;   // turret shot starting x - off screen
var sy                  = -20;   // turret shot starting y - off screen
var turret_been_hit     = false;
var turret_blast_delay  = 25;    // keep blast active on screen for 60 frames
var turret_exp_frame    = 1;     // turret explode start animation frame
var turret_anim_delay   = 3;     // turret explode animation delay
var explosion_play      = false;

// misc variables
var score               = 0;     // starting score
var lives               = 3;     // starting lives
var game_state          = 0;     // game state - 0 = game not started, 1 = game running, 3 = game over
//var ang                 = 0.1;
var start_been_pressed  = false; // stops double press on restart
var fire_been_pressed   = false; // stops auto fire

// input(screen controller) variables
var BTNL, BTNR, BTNF, BTNS; // button - left, right, fire, start
var tap = {};
// use tapping on screen for left, right, fire, start
Bangle.on('drag',e=>tap=e);
BTNL = { read : _=>tap.b && tap.x < 88 && tap.y > 88};
BTNR = { read : _=>tap.b && tap.x > 88 && tap.y > 88};
BTNF = { read : _=>tap.b && tap.x > 88 && tap.y < 88};
BTNS = { read : _=>tap.b && tap.x < 88 && tap.y < 88};


// - sprites -------------------------------------------
// invader sprites
var invader_a =
  require("heatshrink").decompress(atob("hcIwkBiIBBAQoECCQQFBgEQAIMBEhUBDoYWDAYI="));
var invader_b =
  require("heatshrink").decompress(atob("hcIwkBiIBBAQMQAoQEBgISCAYUQAIQAEB4YEBEAgEDAYIA=="));
var boom =
  require("heatshrink").decompress(atob("hcJwkBiMQAIURgMQAgIKBAIICFAIMAAwIWBBAYSIEAgrDiA="));
var inv_shot =
  require("heatshrink").decompress(atob("gcFwkBiERiAABAYQ"));

// turret sprites
var turret =
  require("heatshrink").decompress(atob("h8IwkBiIABAYYACgAHFiEABggADCAInFgITBAAgOPA=="));
var tur_exp_a =
  require("heatshrink").decompress(atob("h8IwkBiMRiACBAAwJEiAABBQgZCAAkAiAJBBoIUBgIABBgQACDIQ9ECQIA=="));
var tur_exp_b =
  require("heatshrink").decompress(atob("h8IwkBiIBBAAUBiADCiMQAwQFDCIYXEB4IABgMAEYQXBiEAAQIQBAoIABDAQUCAAIVBA"));
var shot =
  require("heatshrink").decompress(atob("gMDwkBAoIA=="));


// function to move and animate invader
function move_anim_inv() {
  // invader anim code
  i_anim_delay -= 1;
  if ((i_anim_delay < 0) && !(been_hit)) {
    i_anim_delay = 10;

    inv_frame += 1;
    if (inv_frame > 2) {
      inv_frame = 1;
    }

    // move right
    if (i_dir == 1){
      inv_x += ix_speed;
      if (inv_x >= 142) {
        inv_y += 8; // step down
        i_dir = -1;
      }
    }

    // move left
    if (i_dir < 1){
      inv_x -= ix_speed;
      if (inv_x <= 10) {
        inv_y += 8; // step down
        i_dir = 1;
      }
    }
  }
}


// function to make invader fire
function invader_fire() {
  inv_fire_pause -= 1;

  if (!(inv_fired)) { // so once invader shot is fired it doesn't follow the invader still
    inv_shot_x = inv_x + 8;
    inv_shot_y = inv_y + 18;
  }

  if (inv_fire_pause < 0) {
    inv_fired = true;
    inv_shot_y += 8;
  }
}


// function to make turret explode (when hit) then start back in center
function turret_hit() {
  if (turret_been_hit) {
    if (!(explosion_play)) {
      //Bangle.buzz();
      //Bangle.beep();
    }

    explosion_play = true;
    turret_anim_delay -= 1;
    turret_blast_delay -= 1;

    if (turret_anim_delay < 0) {
      turret_exp_frame += 1;
      if (turret_exp_frame > 2) {
        Bangle.buzz();
        turret_exp_frame = 1;
      }
      turret_anim_delay = 3;
    }

    if (turret_blast_delay < 0) {
      turret_blast_delay = 21;
      turret_been_hit = false;
      explosion_play = false;
      tur_x = 77;   // reset turret x
      tur_y = 148;  // reset turret y
    }
  }
}


// function to make invader explode (when hit) then randomly start somewhere else
function invader_hit() {
  if (been_hit) {
    if (!(boom_play)) {
      Bangle.buzz();
      //Bangle.beep();
    }

    inv_shot_x = -32;      // hide shot
    inv_shot_y = -32;      // hide shot
    inv_fire_pause = 30;   // and reset pause

    boom_play = true;
    blast_delay -= 1;

    if (blast_delay < 0) {
      blast_delay = 15;
      boom_play = false;
      been_hit = false;
      //bx = -32;                         // move boom off screen (following invader)
      //by = -32;
      // generate a random rounded number between 10 and 142;
      inv_x = Math.floor(Math.random() * 142) + 10;
      inv_y = 20;                       // move invader back up after being hit
      i_dir = 1;                        // reset invader direction
    }
  }
}


// - setup stuff ---------------------------------------
function gameStart() {
  setInterval(onFrame, 50);
}


// - main loop -------------------------------------------------------------
function onFrame() {

  // game not started state (title screen) ***************************
  if(game_state == 0) {
    g.clear();


    if (!(BTNS.read())) {
      start_been_pressed  = false; // stops double press on restart
    }


    // draw text during game over state
    g.setFont("4x6", 4);  // set font and size x 4
    g.setColor("#0f0");    // set color (green)
    g.drawString("INVADER", 33, 55);

    g.setColor(fgCol).setFont("6x8").drawString("TAP TO START", 53, 125);
    if (Bangle.isLocked()) {
      g.drawString("[SCREEN LOCKED]", 43, 145);
    }

    // just animate invader
    // invader anim code
    i_anim_delay -= 1;
    if(i_anim_delay < 0) {
      i_anim_delay = 15;

      inv_frame += 1;
      if (inv_frame > 2) {
        inv_frame = 1;
      }
    }


    // draw sprites during game over state
    // next 2 line for a rotating invader on the title screen
    //ang += 0.1;
    //g.drawImage(invader_a, 88, 98, {scale:4, rotate:ang});
    if(inv_frame == 1) {
      g.drawImage(invader_a, 88-22, 85, {scale:4});
    }
    else if(inv_frame == 2) {
      g.drawImage(invader_b, 88-22, 85, {scale:4});
    }

    // reset stuff
    if(tap.b && !(start_been_pressed)) {
      turret_been_hit  = false;
      tur_x            = 77;       // reset turret to center of screen
      tur_y            = 148;      // reset turret y
      inv_x            = 77;       // reset invader to center of screen
      inv_y            = 20;       // reset invader back to top
      i_dir            = 1;        // reset invader direction
      lives            = 3;        // reset lives
      score            = 0;        // reset score
      explosion_play   = false;
      game_state       = 1;
      turret_blast_delay  = 25;
  }


    g.flip();
  }


  // game over state *************************************************
  if(game_state == 3) {
    g.clear();

    // draw text during game over state
    g.setFont("4x6", 2);  // set font and size x 2
    g.setColor(fgCol);    // set color (black)
    g.drawString("SCORE:" + score ,5, 5);
    g.drawString("LIVES:" + lives ,117, 5);
    g.drawString("GAME OVER", 52, 80);


    // draw sprites during game over state
    // - invader frame 2
    g.drawImage(invader_b, inv_x, inv_y, {scale:2});
    g.drawImage(tur_exp_b, tur_x, tur_y, {scale:2});
    g.drawImage(inv_shot, inv_shot_x, inv_shot_y, {scale:2});


    // reset stuff
    if(BTNS.read()) {
      //turret_been_hit  = false;
      //tur_x            = 77;       // reset turret to center of screen
      //tur_y            = 148;      // reset turret y
      //inv_x            = 77;       // reset invader to center of screen
      //inv_y            = 20;       // reset invader back to top
      //i_dir            = 1;        // reset invader direction
      //lives            = 3;        // reset lives
      //score            = 0;        // reset score
      //explosion_play   = false;
      game_state       = 0;
      start_been_pressed  = true;
      //turret_blast_delay  = 25;
    }


    g.flip();
  }


  // not game over state (game running) ******************************
  if(game_state == 1) {
    Bangle.setLCDPower(1); // optional - this keeps the watch LCD lit up
    g.clear();


    if (!(BTNF.read())) {
      fire_been_pressed  = false; // stops auto fire
    }


    // call function to move and animate invader
    move_anim_inv();

    // call function to make invader fire
    invader_fire();


    // check input (screen presses)
    if(BTNL.read() && tur_x >= 12 && !(turret_been_hit)) {
      tur_x -= 6;
    }
    else if(BTNR.read() && tur_x <= 140 && !(turret_been_hit)) {
      tur_x += 6;
    }
    else if(BTNF.read() && !(turret_been_hit) && !(fire_been_pressed) && !(shot_fired)) {
      shot_fired = true;
      fire_been_pressed = true; // stops auto fire
      sx=tur_x + 12;
      sy=tur_y - 7;
    }


    // check for turret shot going off screen before allowing to fire again
    if (shot_fired) {
      sy -= 8;
      if (sy < 22) {
        shot_fired = false;
        sx = -32;
        sy = -32;
      }
    }


    // check for invader shot going off screen before allowing to fire again
    if (inv_shot_y > 150
    ) {
      inv_fired = false;
      inv_shot_x = inv_x - 1;
      inv_shot_y = inv_y + 7;
      inv_fire_pause = 30;
    }


    // check for turret shot and invader collision
    if ((sx >= inv_x) && (sx <= inv_x + 20) && (sy <= inv_y + 14)) {
        sx = -32;
        sy = -32;
        been_hit = true;
        score += 10;
    }


    // check for invader shot and turret collision
    if ((inv_shot_x + 4) >= (tur_x) && (inv_shot_x) <= (tur_x + 24) && (inv_shot_y + 8) >= (tur_y + 6)) {
      if (!(turret_been_hit)) {
        lives -= 1;

        if (lives == 0) {
          game_state = 3;
          Bangle.buzz();
        }
      turret_been_hit = true;
      }
    }


    // - draw sprites ----------------------------------
    // invader sprites
    if(!(been_hit)) {
      if(inv_frame == 1) {
        // - invader frame 1
        g.drawImage(invader_a, inv_x, inv_y, {scale:2});
      }
      else if(inv_frame == 2) {
        // - invader frame 2
        g.drawImage(invader_b, inv_x, inv_y, {scale:2});
      }
    }
    else {
      // - invader explosion
      g.drawImage(boom, inv_x, inv_y, {scale:2});
    }
    // - invader shot
    if (inv_fired) {
      g.drawImage(inv_shot, inv_shot_x, inv_shot_y, {scale:2});
    }
    else {
      g.drawImage(inv_shot, -32, -32, {scale:2});
    }

    // turret sprites
    if(!(turret_been_hit)) {
      // - undamaged turret
      g.drawImage(turret, tur_x, tur_y, {scale:2});
    }
    else {
      if(turret_exp_frame == 1) {
        // - turret explosion frame 1
        g.drawImage(tur_exp_a, tur_x, tur_y, {scale:2});
      }
      else if(turret_exp_frame == 2) {
        // - turret explosion frame 2
        g.drawImage(tur_exp_b, tur_x, tur_y, {scale:2});
      }
    }
    // - turret shot
    g.drawImage(shot, sx, sy, {scale:2});


    // call function to make invader explode then randomly start somewhere else
    invader_hit();


    // call function to make turret explode (when hit) then start back in center
    turret_hit();


    // - draw text -------------------------------------
    g.setFont("4x6", 2);  // set font and size x 2
    g.setColor(fgCol);    // set color (black)
    g.drawString("SCORE:" + score ,5,5);
    g.drawString("LIVES:" + lives ,117,5);


    g.flip();
  }

} // end main loop ---------------------------------------------------------


gameStart();
