import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import ddf.minim.*; 
import java.awt.event.*; 
import javax.swing.Timer; 
import java.util.Random; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class plagasInvasoras extends PApplet {


Minim minim;
AudioPlayer click;
AudioPlayer clickSetting;
AudioPlayer rollOver;
AudioPlayer winSound;
AudioPlayer loseSound;
AudioPlayer shootSound;
AudioPlayer invaderDieSound;
AudioPlayer hitSound;
AudioPlayer refugioSound;
AudioPlayer[] moveSound = new AudioPlayer[4];
AudioPlayer music;
AudioPlayer forest;

PFont myFont;

PImage bg;
PImage nube1;
PImage nube2;
PImage menuBg;
PImage menuBgMk;
PImage menuRef;
PImage menuTitle;
PImage menuTitle2;
PImage menuLogo;
PImage menuLogo2;
PImage menuInfo;
PImage loseBg;
PImage txtInicial;
PImage choclitos;
PImage refugioTxt;
PImage end_base;
PImage end_globo;
PImage end_Bg;
PImage winnerBg;
PImage hombreAlegre;
PImage hombreTriste;
PImage choclos1;
PImage choclos2;
PImage chocloImg;
PImage granjeroPicture;

AnimatedSprite txtIntroSprite;
AnimatedSprite invSeqASprite;
AnimatedSprite invSeqBSprite;
AnimatedSprite invSeqCSprite;
AnimatedSprite invSeqDSprite;

AnimatedSprite granjeroFront;
AnimatedSprite granjeroWalk;
AnimatedSprite granjeroWalkShoot;
AnimatedSprite granjeroStandShoot;
AnimatedSprite granjeroSprite;
AnimatedSprite perroStand;
AnimatedSprite perroWalk;
AnimatedSprite perroBark;
AnimatedSprite perroBarkUp;
AnimatedSprite dogSprite;
AnimatedSprite abejaFlySprite;
AnimatedSprite vaquitaStand;
AnimatedSprite vaquitaWalk;
AnimatedSprite vaquitaSprite;

Granjero granjero;
Invasores invasores;
Assets assets;
Choclo choclo;

ArrayList<AnimatedSprite> invSpriteGrp = new ArrayList();
ArrayList<AnimatedSprite> abejasGrp = new ArrayList();
ArrayList<Choclo> choclos = new ArrayList();
ArrayList<Misil> misiles = new ArrayList();
ArrayList<Refugio> refugios = new ArrayList();

////////////////////////////// GAME VAR
boolean playing = false;
boolean menuOn = true;
boolean gameOver = false;
boolean menuInfoOn = true;
boolean win = false;
boolean stand = true;
boolean edge = false;
boolean misilExist = true;
boolean pixelOnce = false;
boolean armedOn = true;
boolean onFire = true;
boolean hitGranOn = false;
boolean loseOnce = true;
boolean bloodOn = true;
boolean hitOnce= true;
boolean vaquitaFree = false;
float xdir = 1;
float speed = 1;
int[] numbers = new int[8];
float xdirMove = 0.1f;
int lapse = 1000;
int chocloCorrec = 24;
int limitShoot = 1;
float invadersSpeed = 1.18f;
float granjeroPosX = (width/2)-16;
float invPosX;
float invPosY;
int invColor = color(255, 204, 0);
int dead = 0;
int credit = 3;
////////////////////////////// INFO VAR
boolean avanzado = true;
boolean clickOnce = false;
boolean flagOnce = true;
//String[] txtString;
PGraphics graphText;
int txtFrames = 251;
int playIndex = 0;
long previousMillis = 0;     
long interval = 1000;  
// I create an array named "stars",
// it will be filled with 800 elements made with the Star() class.
Star[] stars = new Star[800];
// I create a variable "speed", it"ll be useful to control the speed of stars.
///////////////////////////// ROLL OVER IMAGES
Picture menuTitlePic;
Picture menuTitlePic2;
Picture menuLogoPic;
Picture menuLogoPic2;
Picture menuLogoBPic;
Picture menuLogoBPic2;
Picture menuLogoCPic;
Picture menuLogoCPic2;
Picture nube1Pic;
Picture nube2Pic;
Picture nube3Pic;
Picture nube4Pic;

Explode explo;
Info info;
Slide slideEnd;
MouseOver mouseOver;
Flock flock;




Timer timer;
Clock clock;

ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        //...Perform a task...
        if (gameOver) { theEnd(); }
        else if (win) { winner(); }
        timer.stop();
    }
};

public void setup() {
    settings();
    
    fill(255);
    background(12, 183, 242);
    text("Loading...", width/2, height/2);
    imageMode(CENTER);
    rectMode(CENTER);
    textAlign(CENTER);
    

    myFont = createFont("font/space_invaders.ttf", 32);
    textFont(myFont);
    
    granjeroPicture = loadImage("img/GranjeroFront.png");
    bg = loadImage("img/_Game_BG.jpg");
    nube1 = loadImage("img/nube1.png");
    nube2 = loadImage("img/nube2.png");
    menuBg = loadImage("img/_Menu_BG.jpg");
    menuBgMk = loadImage("img/mk.png");
    menuRef = loadImage("img/_Menu.jpg");
    
    menuTitle = loadImage("img/_Menu_Title.png");
    menuTitle2 = loadImage("img/_Menu_Title2.png");
    menuTitlePic = new Picture(menuTitle, 482, 160);
    menuTitlePic2 = new Picture(menuTitle2, 482, 160);
    
    menuLogo = loadImage("img/_Menu_PresNac.png"); 
    menuLogo2 = loadImage("img/_Menu_PresNac2.png");
    menuLogoPic = new Picture(menuLogo, 476, 474, menuLogo.width/1.2f, menuLogo.height/1.3f);
    menuLogoPic2 = new Picture(menuLogo2, 476, 474, menuLogo2.width/1.2f, menuLogo2.height/1.3f);
    menuLogoCPic = new Picture(menuLogo, 171, 53, menuLogo.width/2, menuLogo.height/2);
    menuLogoCPic2 = new Picture(menuLogo2, 171, 53, menuLogo2.width/2, menuLogo2.height/2);
    menuLogoBPic = new Picture(menuLogo, 528, 483, menuLogo.width/2, menuLogo.height/2);
    menuLogoBPic2 = new Picture(menuLogo2, 528, 483, menuLogo2.width/2, menuLogo2.height/2);
    
    menuInfo = loadImage("img/_MenuInfo.jpg");
    loseBg = loadImage("img/_Lose.jpg");
    winnerBg = loadImage("img/_Win.jpg");
    
    end_base = loadImage("img/baseTransp.png");
    end_globo = loadImage("img/globo.png");
    end_Bg = loadImage("img/_End_BG.jpg");
    winnerBg = loadImage("img/_Win.jpg");
    hombreAlegre = loadImage("img/hombreAlegre.png");
    hombreTriste = loadImage("img/hombreTriste.png");
    chocloImg = loadImage("img/choclo.png");
    choclos1 = loadImage("img/choclos1.png");
    choclos2 = loadImage("img/choclos2.png");
    txtInicial = loadImage("img/textoInicial.png");
    refugioTxt = loadImage("img/refugio.png");
    choclitos = loadImage("img/chocloBarra.png");
    
    ////////////////////////////////// SOUND
    minim = new Minim(this);
    click =  minim.loadFile("sound/Click.wav");
    clickSetting = minim.loadFile("sound/ClickSetting.wav");
    rollOver =  minim.loadFile("sound/RollOver.wav");
    winSound =  minim.loadFile("sound/WinSound.wav");
    loseSound =  minim.loadFile("sound/LoseSound.wav");
    
    shootSound = minim.loadFile("sound/Disparo.wav");
    invaderDieSound = minim.loadFile("sound/FireEq.wav");
    hitSound = minim.loadFile("sound/Die.wav");
    refugioSound = minim.loadFile("sound/Refugio.wav");
    for(int i = 0; i < 4; i++) {
        moveSound[i] = minim.loadFile("sound/"+(i+1)+".wav");
    }
    music = minim.loadFile("sound/Setuan_Alone.wav");
    forest = minim.loadFile("sound/Forest.wav");
    
    //////////////////////////////////////////  ANIMACIONES 
    float sizeMult = 1.2f;
    text("Loading", width/2, height/2);
    PImage[] txtIntroImgs = new PImage[txtFrames];
    for (int i = 0; i < txtFrames; i++) {
        String imageName = "img/txt/txt_" + nf(i, 4) + ".png";
        //txtString = append(txtString, name); // Add "maple" to the end
        txtIntroImgs[i] = loadImage(imageName);
        //println((i%2)==0);

    }
    //loadAnimation(txtString, txtIntroImgs);
    txtIntroSprite = new AnimatedSprite(txtIntroImgs,  12, width/2,height/2,txtIntroImgs[0].width, txtIntroImgs[0].height);
    
    String[] invSeqA = {"img/inv0.png", "img/inv1.png"};
    PImage[] invSeqAImgs = new PImage[invSeqA.length];
    loadAnimation(invSeqA, invSeqAImgs);
    invSeqASprite = new AnimatedSprite(invSeqAImgs,  6, width/2, 60,invSeqAImgs[0].width*sizeMult, invSeqAImgs[0].height*sizeMult );
    
    String[] invSeqB = {"img/inv2.png", "img/inv3.png"};
    PImage[] invSeqBImgs = new PImage[invSeqB.length];
    loadAnimation(invSeqB, invSeqBImgs);
    invSeqBSprite = new AnimatedSprite(invSeqBImgs, 6, width/2, 60,invSeqAImgs[0].width*sizeMult, invSeqAImgs[0].height*sizeMult);
    
    String[] invSeqC = {"img/inv4.png", "img/inv5.png"};
    PImage[] invSeqCImgs = new PImage[invSeqC.length];
    loadAnimation(invSeqC, invSeqCImgs);
    invSeqCSprite = new AnimatedSprite(invSeqCImgs, 6, width/2, 60,invSeqAImgs[0].width*sizeMult, invSeqAImgs[0].height*sizeMult);
    
    String[] invSeqD = {"img/inv6.png", "img/inv7.png"};
    PImage[] invSeqDImgs = new PImage[invSeqD.length];
    loadAnimation(invSeqD, invSeqDImgs);
    invSeqDSprite = new AnimatedSprite(invSeqDImgs, 6, width/2, 60,invSeqAImgs[0].width*sizeMult, invSeqAImgs[0].height*sizeMult);
    
    invasores = new Invasores();
    invasores.init();
    granjero = new Granjero(width/2);
    granjero.init();
    assets = new Assets();
    assets.init();
    info = new Info();
    slideEnd = new Slide();
    slideEnd.init();
    explo = new Explode();
    
    //color[] invColors = {color(255,85,0,255), color(255,0,106,255), color(241,185,0,255),color(0,85,231,255)};
    
    nube1Pic = new Picture(nube1, 160, 105);
    nube2Pic = new Picture(nube2, 743, 93);
    nube3Pic = new Picture(nube1, 1100, 93);
    nube4Pic = new Picture(nube1, 1400, 193);

    for (int i = 0; i < stars.length; i++) {
        stars[i] = new Star();
    }
    
    flock = new Flock();
    for (int i = 0; i < abejasAmount; i++) {
        flock.addBoid(new Boid(width/2,height/2));
    }
    
    for(int a = 0; a < 4; a++) {
        refugios.add(new Refugio(PApplet.parseInt(200*a + 170), 350));
        refugios.get(a).init();
    }
    
    timer = new Timer(1000, taskPerformer);
    mouseOver = new MouseOver();
    
}


public void draw() {
    if ( menuOn || menuInfoOn || gameOver || win ) {
        if (music.isPlaying() == false) {
            playSound(music);
        } 
    } else { music.pause(); }
    
    if ( playing || gameOver || win ) {
        if (forest.isPlaying() == false) {
            playSound(forest);
        } 
    } else { forest.pause(); }
      
    if (playing) {
          game();
          if (bloodOn) { explo.circle(PApplet.parseInt(granjeroSprite.x), PApplet.parseInt(granjeroSprite.y), 10); }
          if (pixelOnce) { explo.rectangle(PApplet.parseInt(invPosX), PApplet.parseInt(invPosY), 4, 2); }        //// EXPLOTA INVASOR INSECTO
          clock.update();
          flock.run();
       
     } else {
            if ( menuOn ) {
               info.menu();
            }
            else if ( menuInfoOn ) {
                info.menuInfo();
            }
            else if ( gameOver ) {  
                info.gameOver();
            }
            else if ( win ) {
                info.winner();
            }
    } 
}


public void restart() {

    xdir = 1;
    xdir *= -1;
    speed = 1;
    dead = 0;
    credit = 3;
    bloodOn = false;
    hitOnce = false;
    stand = true;
    choclos.clear();
    invSpriteGrp.clear();
    invasores = new Invasores();
    invasores.init();

    assets = new Assets();
    assets.init();
    
    refugios.clear();
    for(int a = 0; a < 4; a++) {
        refugios.add(new Refugio(PApplet.parseInt(200*a + 170), 350));
        refugios.get(a).init();
    }

    loseOnce = true;
    gameOver = false;
    win = false;
    hitGranOn = false;
    onFire = false;
    menuOn = false;
    menuInfoOn = false;
    playing = false;
    vaquitaFree = false;
    playIndex = 0;
}

public void youLose() {
    loseSound.play();
    playing = false;
    hitGranOn = true;                   //// DETIENE A LOS INSECTOS
    gameOver = true;
    win = false;
    timer.start(); 
      
}

public void youWin() {
    winSound.play();
    playing = false;
    win = true;
    gameOver = false;
    timer.start();
}

public void winner() {
    win = true;
    playing = false;
    gameOver = false;
}

public void theEnd() {
    playing = false;
    win = false;
    gameOver = true;
}

public void keyPressed() {
    switch(keyCode) {
        case 37:        ////LEFT
            granjero.moveLeft = true;
            granjeroSprite = granjeroWalk;
            dogSprite = perroWalk;
            break;
        case 39:    ////// RIGHT
            granjero.moveRight = true;
            granjeroSprite = granjeroWalk;
            dogSprite = perroWalk;
            break;
        case 32:         ///// SPACEBAR
            if(armedOn) { granjero.shoot(); }
            break; 
        case 38:        /////    UP ARROW
                if(armedOn) { granjero.shoot(); }
            break;
        case 13:                ////// ENTER
            if (gameOver || win) { restart(); }
            break;
    }
}

public void keyReleased() {
    switch(keyCode) {
        case 37:
            granjero.moveLeft = false;
            break;
        case 39:
            granjero.moveRight = false;
            break;
        //case (37 || 39):
        //    break;
    }

    if (!granjero.moveLeft && !granjero.moveRight) {
        granjeroSprite = granjeroFront;
        dogSprite = perroStand;
        stand = true;
    }
}



public void settings() {
    size(960, 540);
}
// Improvements by Greg Borenstein (November 2012):
// - Set speed based on desired FPS
// - playOnce(), loop(), stop functions
// - load images from a directory
// - rename to AnimatedSprite to get around weird windows problem.

// Originally by:
// Daniel Shiffman
// Hanukkah 2011
// 8 nights of Processing examples
// http://www.shiffman.net

// The animation object

class AnimatedSprite {
  float x;  // location for Animation
  float y;  // location for Animation
  float w;  // location for Animation
  float h;  // location for Animation
  int dirX;  // location for Animation
  int shapeColor;  // location for Animation

  // The index into the array is a float!
  // This allows us to vary the speed of the animation
  // It will have to be converted to an int before the actual image is displayed
  float index = 0; 

  // Speed, this will control both the animations movement
  // as well as how fast it cycles through the images
  float speed;
  int fps;
  // The array of images
  PImage[] images;

  boolean playing = false;
  boolean playOnce = true;
  
  AnimatedSprite(String pathToImages, int fps, float x_, float y_) {
    loadImagesFromPath(pathToImages);
    this.x = this.x + x_;
    this.y = this.y + y_;
    this.fps = fps;
    index = 0;
    setFPS(fps);
  }
  
  AnimatedSprite(PImage[] images_,int fps, float x_, float y_, float w_, float h_ ) {
    images = images_;
    this.x = this.x + x_;
    this.y = this.y + y_;
    this.w = this.w + w_;
    this.h = this.h + h_;
    this.fps = fps;
    this.dirX = 1;
    index = 0;
    setFPS(fps);
  }
  
  
  public void loadImagesFromPath(String path) {
    java.io.File folder = new java.io.File(dataPath(path));
    String[] filenames = folder.list();
    images = new PImage[filenames.length];

    for (int i = 0; i < filenames.length; i++) {
      images[i] = loadImage(dataPath(path + "/" + filenames[i]));
    }
  }
  
  public void mirrorX(int dir) {
        this.dirX = dir;
    }
  
  public float getWidth() {
    return this.w;
  }
  
  public float getHeight() {
    return this.h;
  }
  
  public void setFPS(int fps) {
    this.fps = fps;
  }

  public void setSpeed(int fps) {
    speed = fps/(float)frameRate;
  }

  public void playOnce() {
    index = 0;
    playOnce = true;
    playing = true;
  }
  
  public void loop(){
    playing = true;
    playOnce = false;
  }
  
  public void stop(){
    playing = false;
    playOnce = false;
  }
  
  public boolean isPlaying(){
    return playing;
  }
  

  public void draw() {
    // We must convert the float index to an int first!
    int imageIndex = PApplet.parseInt(index);
    pushMatrix();
    scale(this.dirX,1);
    image(images[imageIndex], this.x*this.dirX, this.y,this.w,this.h);
    popMatrix();
  }

  public void update() {
    setSpeed(fps);
    if (playing) {
      // Move the index forward in the animation sequence
      index += speed;
      // If we are at the end, go back to the beginning
      if (index >= images.length) {
        if (playOnce) {
          playing = false;
          index = images.length-1;
        } 
        else {
          // We could just say index = 0
          // but this is slightly more accurate
          index -= images.length;
        }
      }
    }
  }
}

public void loadAnimation(String[] stringArray, PImage[] seq) {
  for (int i = 0; i < stringArray.length; i++) {
    seq[i] = loadImage(stringArray[i]);
  }

}
class Assets {


    
    public void init() {
//      vaquita = createSprite(200, 300);
//      vaquita.scale = .4;
//      vaquita.addAnimation('stand', vaquitaStandSeq);
//      vaquita.addAnimation('walk', vaquitaWalkSeq);
//      vaquita.position.x = 160;
//      vaquita.position.y = 385;
//      vaquita.animation.frameDelay = 12;
        String[] vaquitaWalkSeq = {"img/vaquitaFly1.png", "img/vaquitaFly2.png"};
        String[] vaquitaStandSeq = {"img/vaquitaStand1.png", "img/vaquitaStand2.png"};
        PImage[] vaquitaStandImgs = new PImage[2];
        PImage[] vaquitaWalkImgs = new PImage[2];
        
        loadAnimation(vaquitaStandSeq, vaquitaStandImgs);
        loadAnimation(vaquitaWalkSeq, vaquitaWalkImgs);
        vaquitaStand = new AnimatedSprite(vaquitaStandImgs, 8, 212, 397, 30, 30 );  /////// + width/4 Center of screen
        vaquitaStand.setFPS(4);
        vaquitaStand.loop();
        
        vaquitaWalk = new AnimatedSprite(vaquitaWalkImgs, 8, 212, 397, 30, 30 );  /////// + width/4 Center of screen
        vaquitaWalk.setFPS(12);
        vaquitaWalk.loop();
        
        vaquitaSprite = vaquitaStand;
        
        String[] perroStandSeq = {"img/PerroStand1.png", "img/PerroStand2.png", "img/PerroStand3.png"};
        String[] perroWalkSeq = {"img/PerroWalk1.png", "img/PerroWalk2.png", "img/PerroWalk3.png"};
        String[] perroBarkUpSeq = {"img/PerroLadraArriba1.png", "img/PerroLadraArriba2.png", "img/PerroLadraArriba3.png"};
        String[] perroBarkSeq = {"img/PerroLadraAbajo1.png", "img/PerroLadraAbajo2.png", "img/PerroLadraAbajo3.png"};
        String[] PerroBarkUpSeq = {"img/PerroLadraAbajo1.png", "img/PerroLadraAbajo2.png", "img/PerroLadraAbajo3.png"};
        PImage[] perroStandImgs = new PImage[3];
        PImage[] perroWalkImgs = new PImage[3];
        PImage[] perroBarkImgs = new PImage[3];
        PImage[] perroBarkUpImgs = new PImage[3];
        
        loadAnimation(perroStandSeq, perroStandImgs);
        loadAnimation(perroWalkSeq, perroWalkImgs);
        loadAnimation(perroBarkSeq, perroBarkImgs);
        loadAnimation(PerroBarkUpSeq, perroBarkUpImgs);
        
        perroStand = new AnimatedSprite(perroStandImgs, 8, width/2-16, height-60, 115, 115 );  /////// + width/4 Center of screen
        perroStand.setFPS(4);
        perroStand.loop();
        
        perroWalk = new AnimatedSprite(perroWalkImgs, 8, width/2-16, height-60, 115, 115 );  /////// + width/4 Center of screen
        perroWalk.setFPS(12);
        perroWalk.loop();
        
        perroBark = new AnimatedSprite(perroBarkImgs, 8, width/2-16, height-60, 115, 115 );  /////// + width/4 Center of screen
        perroBark.setFPS(12);
        perroBark.loop();
      
        perroBarkUp = new AnimatedSprite(perroBarkUpImgs, 8, width/2-16, height-60, 115, 115 );  /////// + width/4 Center of screen
        perroBarkUp.setFPS(12);
        perroBarkUp.loop();
        
        dogSprite = perroStand;
        
        //String[] abejaWalkSeq = {"img/Abeja_Camina1.png", "img/Abeja_Camina2.png"};
        String[] abejaFlySeq = {"img/Abeja_Vuela1.png", "img/Abeja_Vuela2.png"};
        PImage[] abejaFlyImgs = new PImage[2];
        loadAnimation(abejaFlySeq, abejaFlyImgs);
        for (int i = 0; i < abejasAmount; i++) {
            float s = random(10, 30);
            abejaFlySprite = new AnimatedSprite(abejaFlyImgs, 16, width/2, height/2, s, s );  /////// + width/4 Center of screen
            abejaFlySprite.setFPS(PApplet.parseInt(random(8,16)));
            abejaFlySprite.loop();
            abejasGrp.add(abejaFlySprite);
        }
    }

    public void update() {
        dogSprite.x = granjeroSprite.x + 100;
        dogSprite.y = granjeroSprite.y;
        dogSprite.update(); 
        dogSprite.draw();
        
        if (vaquitaFree) {
            vaquitaSprite = vaquitaWalk;
            vaquitaSprite.x += random(1, 10) * easing;
            vaquitaSprite.y -= random(0.1f, 3) * easing;
            easing += 0.01f;
            if (vaquitaSprite.x > width + 50) { checking = false; vaquitaFree = false; }
        }
        
        vaquitaSprite.update(); 
        vaquitaSprite.draw();
        
        for (int i = 0; i < abejasAmount; i++) {
            abejasGrp.get(i).update(); 
            abejasGrp.get(i).draw();
        }
    }       
}
boolean checking = true;
float easing = 0.25f;

class Explode {
    int r = 0;
    int t = 0;
    int a = 255;
    int s = 30;
    
    Explode() {
        this.r = 0;
        this.t = 0;
        this.a = 255;
        this.s = 30;
    }
  
      public void circle (int x, int y, int w) {
          pushMatrix();
          noFill();
          strokeWeight(this.s);
          stroke(204, 102, 0, this.a);
          //tint(this.t);
          ellipse(x,y,w+this.r,w+this.r);
          popMatrix();
          this.r += 5;
          this.t -= 1;
          this.s -= 1;
          this.a -= 10;
          if (this.a <= 0) { 
              this.r = 0;
              this.t = 0;
              this.a = 255;
              this.s = 30;
              bloodOn = false; 
          } 
      }
      
      public void rectangle(int x, int y, int w, int s) {
          this.s = s;
          pushMatrix();
          noFill();
          strokeWeight(this.s);
          stroke(255, 255, 255, this.a);
          //tint(this.t);
          rect(x,y,w+this.r,w+this.r);
          popMatrix();
          this.r += 2;
          this.t -= 1;
          this.s -= 1;
          this.a -= 10;
          if (this.a <= 0) { 
              this.r = 0;
              this.t = 0;
              this.a = 255;
              this.s = 30;
              pixelOnce = false; 
          }
      }
}
class Choclo {
    float x;
    float y;
    boolean toDelete;
    
     Choclo(float x, float y)  {
       
        this.x = x;
        this.y = y;
        this.toDelete = false;
     }
  
    public void show() {
        image(chocloImg, this.x, this.y, chocloImg.width, chocloImg.height );
    }
  
    public void evaporate() {
        this.toDelete = true;
    }
  
    public boolean hits (AnimatedSprite enemy) {
      float d = dist(this.x, this.y, enemy.x, enemy.y);
  
    if (d < (enemy.getWidth()/2)) {
            return true;
        } else {
            return false;
        }
    }
  
    public void move () {
      this.y = this.y - 5;
    } 
}
int abejasAmount = 12;
int reduce = 1;
float [] lastDir;

class Flock {
    ArrayList<Boid> boids; // An ArrayList for all the boids
  
    Flock() {
        boids = new ArrayList<Boid>(); // Initialize the ArrayList
        lastDir = new float[abejasAmount];
        for (int i = 0; i < abejasAmount; i++) {
            lastDir[i] = 0;
        }
        
    }
  
    public void run() {
        int i = 0;
        for (Boid b : boids) { 
            b.run(boids);
            
            abejasGrp.get(i).x = b.position.x;
            abejasGrp.get(i).y = b.position.y;
            
            
            if (abejasGrp.get(i).w <= 10) { reduce = 1; }
            else if (abejasGrp.get(i).w > 30) { reduce = -1;}
            abejasGrp.get(i).w = abejasGrp.get(i).w + (0.01f * reduce);
            abejasGrp.get(i).h = abejasGrp.get(i).h + (0.01f * reduce);
            
            if (lastDir.length == abejasAmount) {
                if (abejasGrp.get(i).x > lastDir[i] ) {
                abejasGrp.get(i).mirrorX ( 1 );
                } else { abejasGrp.get(i).mirrorX ( -1 ); }
            }
            lastDir[i] = abejasGrp.get(i).x;
            i++;
        }  // Passing the entire list of boids to each boid individually
    }

    
    public void addBoid(Boid b) {
        boids.add(b);
    }

}


class Boid {

  PVector position;
  PVector velocity;
  PVector acceleration;
  float r;
  float maxforce;    // Maximum steering force
  float maxspeed;    // Maximum speed

    Boid(float x, float y) {
    acceleration = new PVector(0, 0);

    // This is a new PVector method not yet implemented in JS
    // velocity = PVector.random2D();

    // Leaving the code temporarily this way so that this example runs in JS
    float angle = random(TWO_PI);
    velocity = new PVector(cos(angle), sin(angle));

    position = new PVector(x, y);
    r = 2.0f;
    maxspeed = 2;
    maxforce = 0.03f;
  }

  public void run(ArrayList<Boid> boids) {
    flock(boids);
    update();
    borders();
    render();
  }

  public void applyForce(PVector force) {
    // We could add mass here if we want A = F / M
    acceleration.add(force);
  }

  // We accumulate a new acceleration each time based on three rules
  public void flock(ArrayList<Boid> boids) {
    PVector sep = separate(boids);   // Separation
    PVector ali = align(boids);      // Alignment
    PVector coh = cohesion(boids);   // Cohesion
    // Arbitrarily weight these forces
    sep.mult(1.5f);
    ali.mult(1.0f);
    coh.mult(0.3f);
    // Add the force vectors to acceleration
    applyForce(sep);
    applyForce(ali);
    applyForce(coh);
  }

  // Method to update position
  public void update() {
    // Update velocity
    velocity.add(acceleration);
    // Limit speed
    velocity.limit(maxspeed);
    position.add(velocity);
    // Reset accelertion to 0 each cycle
    acceleration.mult(0);
  }

  // A method that calculates and applies a steering force towards a target
  // STEER = DESIRED MINUS VELOCITY
  public PVector seek(PVector target) {
    PVector desired = PVector.sub(target, position);  // A vector pointing from the position to the target
    // Scale to maximum speed
    desired.normalize();
    desired.mult(maxspeed);

    // Above two lines of code below could be condensed with new PVector setMag() method
    // Not using this method until Processing.js catches up
    // desired.setMag(maxspeed);

    // Steering = Desired minus Velocity
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);  // Limit to maximum steering force
    return steer;
  }

  public void render() {
    // Draw a triangle rotated in the direction of velocity
    float theta = velocity.heading2D() + radians(90);
    // heading2D() above is now heading() but leaving old syntax until Processing.js catches up
    
    //fill(200, 100);
    //stroke(255);
    //pushMatrix();

    //translate(position.x, position.y);
    //rotate(theta);
    //beginShape(TRIANGLES);
    //vertex(0, -r*2);
    //vertex(-r, r*2);
    //vertex(r, r*2);
    //endShape();
    //popMatrix();
  }

  // Wraparound
  public void borders() {
    if (position.x < -r) position.x = width+r;
    if (position.y < -r) position.y = height+r;
    if (position.x > width+r) position.x = -r;
    if (position.y > height+r) position.y = -r;
  }

  // Separation
  // Method checks for nearby boids and steers away
  public PVector separate (ArrayList<Boid> boids) {
    float desiredseparation = 25.0f;
    PVector steer = new PVector(0, 0, 0);
    int count = 0;
    // For every boid in the system, check if it's too close
    for (Boid other : boids) {
      float d = PVector.dist(position, other.position);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        // Weight by distance
        steer.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      steer.div((float)count);
    }

    // As long as the vector is greater than 0
    if (steer.mag() > 0) {
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // steer.setMag(maxspeed);

      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.mult(maxspeed);
      steer.sub(velocity);
      steer.limit(maxforce);
    }
    return steer;
  }

  // Alignment
  // For every nearby boid in the system, calculate the average velocity
  public PVector align (ArrayList<Boid> boids) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);
    int count = 0;
    for (Boid other : boids) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.velocity);
        count++;
      }
    }
    if (count > 0) {
      sum.div((float)count);
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // sum.setMag(maxspeed);

      // Implement Reynolds: Steering = Desired - Velocity
      sum.normalize();
      sum.mult(maxspeed);
      PVector steer = PVector.sub(sum, velocity);
      steer.limit(maxforce);
      return steer;
    } 
    else {
      return new PVector(0, 0);
    }
  }

  // Cohesion
  // For the average position (i.e. center) of all nearby boids, calculate steering vector towards that position
  public PVector cohesion (ArrayList<Boid> boids) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);   // Start with empty vector to accumulate all positions
    int count = 0;
    for (Boid other : boids) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.position); // Add position
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);
      return seek(sum);  // Steer towards the position
    } 
    else {
      return new PVector(0, 0);
    }
  }
}
public void game() {
    image(bg, width/2, height/2);                               //// BACKGROUND
    info.game();
    soundInvaders();
    
    nube1Pic.x += xdirMove;
    nube2Pic.x += xdirMove * 1.6f;
    nube3Pic.x += xdirMove;
    nube4Pic.x += xdirMove;
    nube1Pic.display();
    nube2Pic.display();
    nube3Pic.display();
    nube4Pic.display();
    
    granjero.update();
    invasores.update();
    assets.update();

    if (dead > 45) { lapse = 100; speed = 1.06f; interval = 300; }
    else if (dead == 40 ) { lapse = 200; speed = 1.05f; interval = 400; playIndex = 3; }
    else if (dead == 35 ) { lapse = 400; speed = 1.04f; interval = 500;  }
    else if (dead == 30 ) { lapse = 600; speed = 1.03f; interval = 600; playIndex = 2; }
    else if (dead == 20 ) { lapse = 700; speed = 1.02f; interval = 700; }
    else if (dead == 10 ) { lapse = 800; speed = 1.01f; interval = 800; playIndex = 1; }
    else if (dead == 5 ) { lapse = 900; speed = 1.005f; interval = 900; }
    else if (dead < 5 ) { lapse = 1000; speed = 1; interval = 1000; playIndex = 0; }

    for(int a = 0; a < 4; a++) {
        refugios.get(a).render();
    }

    for (int i = misiles.size()-1; i >= 0; i--) {
        int[] refugioState = {0,0,0,0};
        for(int a = refugios.size()-1; a >= 0; a--) {        /// CUATRO REFUGIOS
            for(int r = refugios.get(a).yGrid-1; r >= 0; r--) {
                for(int c = refugios.get(a).xGrid-1; c >= 0; c--) {
                    if (refugios.get(a).segments[r][c][2] == 1) {
                        float xx = refugios.get(a).x + refugios.get(a).segments[r][c][0];
                        float yy = refugios.get(a).y + refugios.get(a).segments[r][c][1];
                        
                        if (misiles.get(i).getit(xx, yy) && flagOnce) {
                            refugios.get(a).del(r,c);
                            misiles.get(i).evaporate();
                            fill(random(0,255),random(0,255),random(0,255));
                            rect(xx, yy, refugios.get(a).xGridSize, refugios.get(a).yGridSize);
                            playSound(refugioSound);
                            flagOnce = false;
                        }
                        refugioState[a] += refugios.get(a).segments[r][c][2];
                    }
                    flagOnce = true;
                }
            }
        }
        if (refugioState[0] == 1 && checking) { vaquitaFree = true; }
        misiles.get(i).show();
        misiles.get(i).move();

        if (misiles.get(i).hits(granjeroSprite)) {
            if (hitOnce) {                                             /////////// HITS GRANJERO
                if (credit > 1) { credit--; } else { youLose(); }
                playSound(hitSound);
                bloodOn = true;
                hitOnce = false;
            }
        }

        if (misiles.get(i).y > height) { misiles.get(i).evaporate(); }
        if (misiles.get(i).toDelete) { misiles.remove(i); }
    }

    if (misiles.size() > 0) { misilExist = true; } else { misilExist = false; }
    
    for (int i = choclos.size()-1; i >= 0; i--) {                     ///////// DISPAROS
        for (int z = invSpriteGrp.size()-1; z>= 0; z--) {       //// CHOCLOS HITS INSECTOS INVASORES
            if (invSpriteGrp.get(z).y > height) { youLose(); }
            
            if (choclos.get(i).hits(invSpriteGrp.get(z))) {

                invPosX = invSpriteGrp.get(z).x;
                invPosY = invSpriteGrp.get(z).y;
                invColor = invSpriteGrp.get(z).shapeColor;
                pixelOnce = true; onFire = true;
                playSound(invaderDieSound);

                if (stand) { granjeroSprite = granjeroFront;  dogSprite = perroStand; }
                invSpriteGrp.remove(z);
                choclos.get(i).evaporate();
                if (dead < 47) { dead++; } else { dead = 48; youWin(); }
                if (speed <= invadersSpeed) { 
                    //speed = speed + 0.01;
                    xdir = xdir * speed;
                }
            }
        }
        
        Choclo choclets = choclos.get(i);
        choclets.show();
        choclets.move();
        if(choclos.size()-1 >= limitShoot) { armedOn = false; } else { armedOn = true; }
        if (choclets.y < 0) { choclets.evaporate(); }
        if (choclets.toDelete) { choclos.remove(i); }
    }

    if (choclos.size() > 0 && stand ) {                              //// CAMBIO DE ANIMACIONES
        granjeroSprite = granjeroStandShoot ; 
        if (dead < 20) { dogSprite = perroBarkUp; }  else { dogSprite = perroBark; }
    }

    else if (choclos.size() > 0 && !stand ) { granjeroSprite = granjeroWalkShoot; }

    if (choclos.size() > 0) {                                                                     
        if (choclos.get(choclos.size()-1).y < height/2) {                /// SI LOS CHOCLOS CRUZAN lA MITAD DE LA PANTALLLA
            if (stand) { granjeroSprite = granjeroFront;  dogSprite = perroStand; }
            else { granjeroSprite = granjeroWalk; }
        }
    }
}
class Granjero {
  
    float x;
    int xdir;
    int speed;
    boolean moveLeft;
    boolean moveRight;
    
    Granjero (float x_) {
        this.x += x_;
        this.xdir = 0;
        this.speed = 5;
        this.moveLeft = false;
        this.moveRight = false;
    }
    
    public void init() {
      
        String[] granjeroFrontSeq = {"img/GranjeroFront1.png", "img/GranjeroFront2.png", "img/GranjeroFront3.png"};
        String[] granjeroWalkSeq = {"img/GranjeroWalk1.png", "img/GranjeroWalk2.png", "img/GranjeroWalk3.png"};
        String[] granjeroWalkShootSeq = {"img/GranjeroWalkShoot1.png", "img/GranjeroWalkShoot2.png", "img/GranjeroWalkShoot3.png"};
        String[] granjeroStandShootSeq = {"img/GranjeroStandShoot1.png", "img/GranjeroStandShoot2.png", "img/GranjeroStandShoot3.png"};

        PImage[] granjeroFrontImgs = new PImage[3];
        PImage[] granjeroWalkImgs = new PImage[3];
        PImage[] granjeroWalkShootImgs = new PImage[3];
        PImage[] granjeroStandShootImgs = new PImage[3];
        
        loadAnimation(granjeroFrontSeq, granjeroFrontImgs);
        loadAnimation(granjeroWalkSeq, granjeroWalkImgs);
        loadAnimation(granjeroWalkShootSeq, granjeroWalkShootImgs);
        loadAnimation(granjeroStandShootSeq, granjeroStandShootImgs);
      
        granjeroFront = new AnimatedSprite(granjeroFrontImgs, 8, this.x, height-61, 115, 115 );  /////// + width/4 Center of screen
        granjeroFront.setFPS(4);
        granjeroFront.loop();
        
        granjeroWalk = new AnimatedSprite(granjeroWalkImgs, 8, this.x, height-61, 115, 115 );  /////// + width/4 Center of screen
        granjeroWalk.setFPS(12);
        granjeroWalk.loop();
        
        granjeroWalkShoot = new AnimatedSprite(granjeroWalkShootImgs, 8, this.x, height-61, 115, 115 );  /////// + width/4 Center of screen
        granjeroWalkShoot.setFPS(12);
        granjeroWalkShoot.loop();
        
        granjeroStandShoot = new AnimatedSprite(granjeroStandShootImgs, 8, this.x, height-61, 115, 115 );  /////// + width/4 Center of screen
        granjeroStandShoot.setFPS(12);
        granjeroStandShoot.loop();
        
        granjeroSprite = granjeroFront;
        granjeroPosX = granjeroSprite.x;
    }

    public void reset() {
        
        granjeroSprite.x = width/2-16;
        granjeroPosX = granjeroSprite.x;
        granjeroSprite.y = height-61;
    }

    public void update() {
        if(this.moveLeft) {
            this.move(-1);
            granjeroSprite.mirrorX ( -1 );
            dogSprite.mirrorX ( 1 );
            chocloCorrec = -24;
        } else if(this.moveRight) {
            this.move(1);
            granjeroSprite.mirrorX ( 1 );
            dogSprite.mirrorX ( -1 );
            chocloCorrec = 24;
        }
        if(granjeroSprite.x < 20) {
            granjeroPosX = 20;
        }
        if(granjeroSprite.x > width-20) {
            granjeroPosX = width-20;
        }
        granjeroSprite.x = granjeroPosX;
        granjeroSprite.update(); 
        granjeroSprite.draw();
    }

    public boolean hits(AnimatedSprite enemy) {

        float d = dist(granjeroSprite.x, granjeroSprite.y, enemy.x, enemy.y);
        
        if (d < (enemy.w/1.5f)) {
            return true;
        } else {
            return false;
        }
    }

    public void move(float speedMult) {
        granjeroPosX += (this.speed*speedMult);
        stand = false;
    }

    public void shoot() {
        shootSound.setGain(0.3f);
        playSound(shootSound);
        choclos.add(new Choclo(granjeroSprite.x + chocloCorrec, height-60));
    }
}
class Info {
    String textWin;
    String textGameOver;
    
    Info () {
       this.textWin = "La biotecnologia en mis\ncultivos y tu habilidad\nnos pusieron a salvo\nde las Plagas";
       this.textGameOver = "Gracias a la\nbiotecnologia, las perdidas\nno fueron grandes.\nTe espero en el\nproximo juego";
    }
  
      public void menu () {
              image(menuBg, width/2, height/2);
              ScrollText();
              image(menuBgMk, width/2, height/2);
              renderStarField();
              menuTitlePic.display();
      
          if (mouseOver.pic(menuTitlePic)) {
                menuTitlePic2.display();
      
                if (clickOnce) {
                  menuOn = false;
                  menuInfoOn = true;
                  clickOnce = false;
                  playSound(clickSetting);
                }
          } else { menuTitlePic.display();  }
      
          if (mouseOver.pic(menuLogoPic)) { 
            menuLogoPic2.display();
            if (clickOnce) { 
                      goToLink(); 
                      clickOnce = false;
                      playSound(clickSetting);
                    }
          } else { menuLogoPic.display();  }
          
           invSeqASprite.x = 700;
           invSeqBSprite.x = invSeqASprite.x+50;
           invSeqCSprite.x = invSeqBSprite.x+50;
           invSeqASprite.loop(); invSeqASprite.update(); invSeqASprite.draw();
           invSeqBSprite.loop(); invSeqBSprite.update(); invSeqBSprite.draw();
           invSeqCSprite.loop(); invSeqCSprite.update(); invSeqCSprite.draw();
      }
      
      public void menuInfo() {
          image(menuInfo, width/2, height/2);
          noStroke();
          if (mouseOver.rectan(575, 280, 200, 40)) {       /////// PRINCIPIANTE BUTTON
                fill(128,100,128);
                if (clickOnce) {
                    playSound(clickSetting);
                    restart();
                    avanzado = false;
                    menuInfoOn = false;
                    clickOnce = false;
                    playing = true;
                    limitShoot = 3;
                    invadersSpeed = 1.13f;
                    clock = new Clock();
                    
                }
          } else { fill(128,0,128); }
          
          rect(575, 280, 200, 40);
              
          if (mouseOver.rectan(575, 325, 200, 40)) {        /////// EXPERTO BUTTON
              fill(128,100,128);
              if (clickOnce) {
                  playSound(clickSetting);
                  restart();
                  avanzado = true;
                  menuInfoOn = false;
                  clickOnce = false;
                  playing = true;
                  limitShoot = 1;
                  invadersSpeed = 1.18f;
                  clock = new Clock();
                  
              }
          } else { fill(128,0,128);  }
          
          rect(575, 325, 200, 40);
          fill(255);
          textSize(18);
          text("Principiante", 575, 288);
          text("Avanzado", 575, 332);
      }
      
      public void game() {
          fill(255);
          textFont(myFont);
          textSize(16);
          text("<PUNTOS: " + dead + ">" , 95, 30);
          text("<TIEMPO: " + clock.elapsed + ">" , 395, 30);
          if (avanzado) { text("Avanzado", 650, 30); } else { text("Principiante", 650, 30); }
          //text("<CREDITO: " + credit + ">" , 850, 30);
          fill(210,105,30);
          if (credit > 0) { 
              for(int a = 0; a < credit; a++) {
                  image(granjeroPicture, 850+(30*a), 27, granjeroPicture.width/2, granjeroPicture.height/2);
              }
          }
          image(refugioTxt, 495, 400, refugioTxt.width/2, refugioTxt.height/2);
      }
        
      public void winner() {
          slideEnd.display(textWin);
        }
        
      public void gameOver() {
          slideEnd.display(textGameOver);
      }
}


class Slide {
    
    int points;
    float[][] posRand;
    
    Picture winnerBgPic;
    Picture end_globoPic;
    Picture end_baseTransp;
    Picture hombreAlegrePic;
    Picture hombreTristePic;
    Picture choclos1Pic;
    Picture choclos2Pic;
    
    Slide() {
        this.points = 200;
        this.posRand = new float[points][3];
    }
    
    public void init() {
        winnerBgPic = new Picture(winnerBg, width/2, height/2);
        end_globoPic = new Picture(end_globo, 507, 150);
        end_baseTransp = new Picture(end_base, 525, 340, end_base.width/1.4f, end_base.height/1.4f);
        hombreAlegrePic = new Picture(hombreAlegre, 237, 396);
        hombreTristePic = new Picture(hombreTriste, 237, 396);
        choclos1Pic = new Picture(choclos1, 752, 353);
        choclos2Pic = new Picture(choclos2, 752, 353);
        nube1Pic = new Picture(nube1, 160, 105);
        nube2Pic = new Picture(nube2, 743, 93);
        nube3Pic = new Picture(nube1, 1100, 93);
        nube4Pic = new Picture(nube1, 1400, 193);

        for (int y = 0; y < points; y++) {
            float [] pos = {random(0, width), random(0, height/2), random(0.5f,4)};
            for (int x = 0; x < 3; x++) {
                posRand[y][x] = pos[x];
            }
        }   
    }

    public void display(String txt) {

        image(bg, width/2, height/2);
        fill(150,140,255);  
        ////////// ESTRELLAS
        for (int i = 0; i < points; i++) {
            float m = 1;
            if (i % 10 == 0) { m = random(1,2); }
            rect(posRand[i][0], posRand[i][1], posRand[i][2] * m, posRand[i][2] * m);
        }

        if (nube2Pic.x >= width || nube2Pic.x <= 0) {   /////// NUBES
            xdirMove *= -1;
        }
        
        nube1Pic.x += xdirMove;
        nube2Pic.x += xdirMove * 1.6f;
        nube3Pic.x += xdirMove;
        nube4Pic.x += xdirMove;
        nube1Pic.display();
        nube2Pic.display();
        nube3Pic.display();
        nube4Pic.display();
        if (mouseOver.pic(choclos1Pic)) { choclos1Pic.display();} else { choclos2Pic.display(); }
        end_baseTransp.display();

        if (mouseOver.pic(menuLogoBPic)) { 
      menuLogoBPic2.display();
      if (clickOnce) { 
                goToLink();
                clickOnce = false;
                playSound(click);
            }
    } else { menuLogoBPic.display();  }

    if (mouseOver.pic(menuLogoCPic)) { 
      menuLogoCPic2.display();
      if (clickOnce) { 
                goToLink();
                clickOnce = false;
                playSound(click);
            }
    } else { menuLogoCPic.display();  }

        if (gameOver) { hombreTristePic.display(); } else { hombreAlegrePic.display(); }
        
        end_globoPic.display();
        noStroke();
        fill(128,0,128);
        rect(605-158, 325, 110, 40);
        rect(605, 325, 110, 40);
        textAlign(CENTER);
        fill(255,200,0);
        textSize(10);
        textLeading(12);
        text("PLAGAS\nCONTROLADAS: ", 450, 363);
        text("TIEMPO\nDE JUEGO: ", 610, 363);
        //rect(523, 410, 233, 25);
        if (mouseOver.rectan(523, 410, 233, 25)) {
            textSize(26);
            if (clickOnce) {
                clickOnce = false;
                menuOn = false;
                menuInfoOn = true;
                clickOnce = false;
                playSound(click);
            }
        } else { textSize(24);  }
        text("<VOLVE A JUGAR>", 525, 419);
        textSize(24);
        text("TU PUNTAJE: ", 530, 293);
        
        if (!gameOver) { fill(25,160,25); }
        if (gameOver) { text("NO ES TAN GRAVE", 530, 100); } else { text("GANASTE", 530, 100); }
        fill(255,70,0);
        textSize(18);
        textLeading(26);
        text(txt, 530, 128);
        fill(255,255,255);
        textSize(18);
        text("FIN DE ESTA PARTIDA", 820, 53);
        text(dead, 450, 333);  ////////////// PUNTAJE
        text(clock.elapsed, 606, 333);
    }
}



class Clock {
    // this.hr;
    // this.mn;
    int sc;
    int lastSec;
    int totalSec;
    int elapsed;
    String total_hr;
    String total_mn;
    String total_sc;
    String elapsedString;
    
    public void update() {
        // this.hr = hour();
        // this.mn = minute();
        this.sc = second();
        if (this.sc != lastSec) { totalSec++; }
        lastSec = this.sc;
        total_hr = pad(floor(totalSec / 3600));
        totalSec %= 3600;
        total_mn = pad(floor(totalSec / 60));
        total_sc = pad(totalSec % 60);
        elapsed = totalSec;
        elapsedString = total_hr + ":"+ total_mn + ":" + total_sc;
    }
}

public String pad(int number) {
  if (number < 10) { return str('0' + number); } else { return str(number); } 
}

public class Picture {
    float x, y;
    float w, h;
    PImage pic;
    
    Picture(PImage pic, float x, float y) {
        this(pic, x, y, pic.width, pic.height); 
    }
    Picture(PImage pic, float x, float y, float w, float h) {
        this.x = x;
        this.y = y;
        this.pic = pic;
        this.w = w; 
        this.h = h;
    }
    public void display() {
        image(this.pic, this.x, this.y, this.w, this.h);
    }
}


class MouseOver {
    float x;
    float xx;
    float y;
    float yy;

    public boolean rectan(float cx, float cy, float cw, float ch) {
        this.x = cx - cw/2;
        this.xx = cx + cw/2;
        this.y = cy - ch/2;
        this.yy = cy + ch/2;
    
        if ((mouseX > this.x && mouseX < this.xx && mouseY > this.y && mouseY < this.yy)) {
            // if (roll) { playSound(rollOver); roll = false; }
            return true;
        } else {  return false; }
    }
    
    public boolean pic(Picture img) {
          
          this.x = img.x - img.w/2;
          this.xx = img.x + img.w/2;
          this.y = img.y - img.h/2;
          this.yy = img.y + img.h/2;
        
          if ((mouseX > this.x && mouseX < this.xx && mouseY > this.y && mouseY < this.yy)) {
              return true;
          }  else { return false; }
    }
}

public void soundInvaders(){
    long currentMillis = millis();
    
    if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
        if (moveSound[playIndex].isPlaying() == false) {
            playSound(moveSound[playIndex]);
        }
    }
}

public void playSound(AudioPlayer sound) {
      sound.pause();
      sound.rewind();
      sound.play();
}

public void mousePressed() {
    clickOnce = true;
    //console.log("clickOnce: " + clickOnce  );
}


public void mouseReleased() {
    clickOnce = false;
    //console.log("clickOnce: " + clickOnce );
}

public void goToLink() {
  link("https://www.argentina.gob.ar/agroindustria"); 
}
class Invasores {

    float center;
    int ranRange;
  
    Invasores() {
        xdir = 1;
        speed = 1;
        this.center = (width/2) + 188;
    }
  
    public void init() {
      //int index = 0;
      for (int j = 0; j < 4; j++) {       ///////// CREATE ARRAY DE INSECTOS
        for (int i = 0; i < 12; i++) {
  
          String[] invStrings = {"img/inv"+j*2+".png", "img/inv"+(j*2+1)+".png"};
          //String[] invStrings = {"img/inv0.png", "img/inv1.png"};
          PImage[] newInvImgs = new PImage[2];
          AnimatedSprite newInvasor;
          loadAnimation(invStrings, newInvImgs);
          newInvasor = new AnimatedSprite(newInvImgs, 8, ((i*invSeqASprite.getWidth()*1.3f)) + width/4, (invSeqASprite.getWidth()*j)+invSeqASprite.getWidth()+30, 37, 37 );  /////// + width/4 Center of screen
          newInvasor.setFPS(4);
          newInvasor.loop();
          //invSpriteGrp[index] = newInvasor;
          invSpriteGrp.add(newInvasor);
          //index++;
          //newInvasor.shapeColor = invColors[j] ;
        }
      }
    }
  
  
    public void update() {
  
      for (int i = 0; i < invSpriteGrp.size(); i++) {                                     ///////// INSECTOS INVASORES GRUPO MUEVEN
  
            if (!hitGranOn) { invSpriteGrp.get(i).x += xdir; } 
            else { invSpriteGrp.get(i).x += random(-1.5f, 1.5f); }

            if (loseOnce) {
                if (granjero.hits(invSpriteGrp.get(i))) {                                           /////// SI ELGRANJERO ES TOCADO POR INSECTOS
                    loseOnce = false;
                    youLose();
                }
            }

            if (!misilExist) {                /////// MISILES DE INSECTOS
            
                if (i == 0) { numbers = randNums(1,48,8); } 
                  
                hitOnce = true;
                boolean check = false;
                check = isInArray(numbers, i);
                
                if (check) {
                    Misil misil = new Misil(invSpriteGrp.get(i).x, invSpriteGrp.get(i).y);
                    misiles.add(misil);
                }
            }
                
            invSpriteGrp.get(i).x += xdir; 
            invSpriteGrp.get(i).update(); 
            invSpriteGrp.get(i).draw();
            
            if (invSpriteGrp.get(i).x >= width || invSpriteGrp.get(i).x <= 0) {   /////// SI TOCAN EL BORDE CANVAS
                edge = true;
            }
      }
  
      if (edge) {           /////// BAJANDO CUANDO TOCA BORDE
          //printArray(randNums(1,48,8));
          if (speed <= 1.19f) { 
              speed = speed + 0.01f;
              xdir = xdir * speed;
          }

          xdir = xdir * -1;

          for (int i = 0; i < invSpriteGrp.size(); i++) {
              invSpriteGrp.get(i).y += (invSpriteGrp.get(i).getHeight()/2);
          }
          edge = false;
      }
    }
  
    public void initMenu() {
  
      //invMenuGrp = new Group();
  
      //for (let i = 0; i < 3; i++) {
      //    var newInvasor = createSprite(((i*invSeqA.getWidth()*1.6)) + this.center, 60);  /////// + width/4 Center of screen
      //    newInvasor.scale = 1.4;
      //    //newInvasor.shapeColor = invColors[j] ;
      //    newInvasor.addAnimation('stand', secuencias[i]);
      //    newInvasor.animation.frameDelay = 12;
      //    invMenuGrp.add(newInvasor);
      //}
    }
}


private static boolean isInArray(int[] nums, int num) {
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] == num) {
            return true;
        }
    }
    return false;
}




public static int[] randNums(int start, int end, int count) {
    Random rng = new Random();

    int[] result = new int[count];
    int cur = 0;
    int remaining = end - start;
    for (int i = start; i < end && count > 0; i++) {
        double probability = rng.nextDouble();
        if (probability < ((double) count) / (double) remaining) {
            count--;
            result[cur++] = i;
        }
        remaining--;
    }
    return result;
}
class Misil {
    float x;
    float y;
    float w;
    float h;
    boolean toDelete;
    
    Misil(float xx, float yy) {
        this.x = xx;
        this.y = yy;
        this.toDelete = false;
    }
    
    public void show() {
        noStroke();
        fill(255);
        this.w = 5;
        this.h = 12;
        rect( this.x, this.y, this.w, this.h );
    }
  
    public void evaporate() {
        this.toDelete = true;
    }
  
    public boolean hits( AnimatedSprite obj) {
        float d = dist(this.x, this.y, obj.x, obj.y);
        if (d < (obj.getWidth()/6)) {
          return true;
        } else {
          return false;
        }
    }
  
    public boolean getit(float xx, float yy) {
        float d = dist(this.x, this.y, xx, yy);
        if (d < 18) {
            return true;
        } else {
            return false;
        }
    }
  
    public void move() {
        this.y = this.y + 2;
    } 
}
class Refugio {
  
    float x;
    float y;
    float s;
    int xGrid;
    int yGrid;
    int xGridSize;
    int yGridSize;
    int fillet;
    int imageSize;
    
    PGraphics img;
    PGraphics mk;
    PImage imgClone;
    
    int[][][] segments;
    
    Refugio(float xx, float yy) {

        this.x = xx;
        this.y = yy;
        this.yGrid = 3;
        this.xGrid = 3;
        this.fillet = 0;
        this.xGridSize = PApplet.parseInt(choclitos.width/xGrid);
        this.yGridSize = PApplet.parseInt(choclitos.height/yGrid);
        this.img = createGraphics(choclitos.width, choclitos.height);
        this.mk = createGraphics(choclitos.width, choclitos.height);
        this.imageSize = choclitos.width;
        
        this.img.beginDraw();
        
        this.mk.imageMode(CENTER);
        this.mk.rectMode(CENTER);
        this.img.imageMode(CENTER);
        this.img.rectMode(CENTER);
        this.img.rectMode(CENTER);
        this.segments = new int[yGrid][xGrid][3];
        
        this.img.image(choclitos, this.img.width/2, this.img.height/2);     /// IMAGEN A MASCAREAR
        this.img.endDraw();
    }
    
    public void init() {
        
        for(int r = 0; r < this.yGrid; r++) {
            for(int c = 0; c < this.xGrid; c++) {
              
                //float[] array = {( c*this.s*2) + this.s, r*this.s*2+this.s, 1};
                int[] array = { (this.xGridSize * c)  , (this.yGridSize * r) , 1};
                
                for(int i = 0; i < 3; i++) {
                    this.segments[r][c][i] = array[i];     ///CENTER MODE ON CREATE GRAPHICS
                 // this.canvasPos[r][c] = new Array(this.x + (c*this.s*2) - this.s*2, this.y + (r*this.s*2) - this.s*2);     ///CENTER OF EACH SEGMENTS RELATIVE TO CANVAS
                }
            }
        }
    }

    public void del(int r, int c) {
        this.segments[r][c][2] = 0;
    }

    public void render() {
        //this.mk.fill(0,0,255);
        rectMode(CENTER);
        for(int r = 0; r < this.yGrid; r++) {
            for(int c = 0; c < this.xGrid; c++) {
                if (this.segments[r][c][2] == 1) {        
                    this.mk.beginDraw();
                    //strokeWeight(2);
                    this.mk.rect(this.segments[r][c][0],   this.segments[r][c][1],   this.xGridSize-this.fillet,   this.yGridSize-this.fillet);
                    
                    //fill(0,255,255);
                    //rect(this.segments[r][c][0] + this.x,   this.segments[r][c][1]+this.y,   this.xGridSize-this.fillet,   this.yGridSize-this.fillet);
                    // this.img.ellipse(this.segments[r][c][0],this.segments[r][c][1],5,5);
                    this.mk.endDraw();
                }
            }
        }
        //imageMode(CENTER);
        manualMask(img, mk );
        //this.img.beginDraw();
        //this.img.mask( this.mk.get() );
        
        //image(choclitos, this.x, this.y);
        image(this.img, this.x+this.xGridSize, this.y+yGridSize);
        //this.img.endDraw();
        this.mk.clear();

    }
}

private void manualMask(PGraphics display, PGraphics mask) {
    mask.loadPixels();
    display.beginDraw();
    display.loadPixels();
    for (int i = 0; i < display.pixels.length; i++) {
        int d = display.pixels[i];
        // mask alpha
        int m_a = mask.pixels[i] & 0xFF;
        // display alpha
        int d_a = (d >> 24) & 0xFF;
        // output alpha (do not change alpha if already transparent)
        int o_a;
        if( m_a < d_a ) {
        o_a = m_a;
        display.pixels[i] = (o_a << 24) | (0x00FFFFFF & d);
        }
    }
    display.updatePixels();
    display.endDraw();
}
public void ScrollText() {
  txtIntroSprite.loop(); txtIntroSprite.update(); txtIntroSprite.draw();
  //fill(255);
  //text(yTxt,mouseX,mouseY);
  //float w = -width*0.6;
  //graphText.beginDraw();
  //graphText.clear();
  //graphText.textFont(myFont);
  ////graphText.background(102);
  ////graphText.stroke(255);
  //graphText.fill(238, 213, 75);
  ////graphText.textLeading(15);
  //graphText.textSize(32);
  //graphText.textAlign(CENTER);
  //graphText.rotateX(radians(-45));
  //graphText.text(txt, 480, yTxt);
  //graphText.endDraw();

  //pushMatrix();
  //rotateX(radians(-45));
  //imageMode(CENTER);
  //image(graphText, width/2,height/2);
  
  //popMatrix();
  
  //translate(width/4, 0,600);
  //textLeading(1);
  //fill(238, 213, 75);
  //textSize(28);
  //textAlign(CENTER);
 
  //text(txt, -w/2, yTxt, w, height*10);
  //text(txt, -w/2, yTxt);

  //if( yTxt > -700) { yTxt-=2; } else { yTxt = 1200; }
}
// Daniel Shiffman
// http://codingtra.in
// http://patreon.com/codingtrain
// Code for: https://youtu.be/17WoOqgXsRM
// I create a "Star" Class.

class Star {

  // I create variables to specify the x and y of each star.
  float x;
  float y;
  // I create "z", a variable I'll use in a formula to modify the stars position.
  float z;
  // I create an other variable to store the previous value of the z variable.
  // (the value of the z variable at the previous frame).
  float pz;

  Star() {

    // I place values in the variables
    x = random(-width/2, width/2);
    // note: height and width are the same: the canvas is a square.
    y = random(-height/2, height/2);
    // note: the z value can't exceed the width/2 (and height/2) value,
    // beacuse I'll use "z" as divisor of the "x" and "y",
    // whose values are also between "0" and "width/2".
    z = random(width/2);
    // I set the previous position of "z" in the same position of "z",
    // which it's like to say that the stars are not moving during the first frame.
    pz = z;
  }



  public void update() {
    // In the formula to set the new stars coordinates
    // I'll divide a value for the "z" value and the outcome will be
    // the new x-coordinate and y-coordinate of the star.
    // Which means if I decrease the value of "z" (which is a divisor),
    // the outcome will be bigger.
    // Wich means the more the speed value is bigger, the more the "z" decrease,
    // and the more the x and y coordinates increase.
    // Note: the "z" value is the first value I updated for the new frame.
    z = z - speed;
    // when the "z" value equals to 1, I'm sure the star have passed the
    // borders of the canvas( probably it's already far away from the borders),
    // so i can place it on more time in the canvas, with new x, y and z values.
    // Note: in this way I also avoid a potential division by 0.
    if (z < 1) {
      z = width/2;
      x = random(-width/2, width/2);
      y = random(-height/2, height/2);
      pz = z;
    }
  }
  public void show() {
    fill(255);
    noStroke();

    // with theese "map", I get the new star positions
    // the division x / z get a number between 0 and a very high number,
    // we map this number (proportionally to a range of 0 - 1), inside a range of 0 - width/2.
    // In this way we are sure the new coordinates "sx" and "sy" move faster at each frame
    // and which they finish their travel outside of the canvas (they finish when "z" is less than a).
    float sx = map(x / z, 0, 1, 0, width/2);
    float sy = map(y / z, 0, 1, 0, height/2);
    // I use the z value to increase the star size between a range from 0 to 16.
    float r = map(z, 0, width/2, 8, 0);
    //ellipse(sx, sy, r, r);
    rect(sx, sy, r, r);
    // Here i use the "pz" valute to get the previous position of the stars,
    // so I can draw a line from the previous position to the new (current) one.
    float px = map(x / pz, 0, 1, 0, width/2);
    float py = map(y / pz, 0, 1, 0, height/2);
    // Placing here this line of code, I'm sure the "pz" value are updated after the
    // coordinates are already calculated; in this way the "pz" value is always equals
    // to the "z" value of the previous frame.
    pz = z;
    stroke(255);
    //line(px, py, sx, sy);
  }
  

        
}

public void renderStarField() {
            //speed = map(mouseX, 0, width, 0, 50);
        pushMatrix();
        speed = 1;
        // I shift the entire composition,
        // moving its center from the top left corner to the center of the canvas.
        translate(width/2, height);
        // I draw each star, running the "update" method to update its position and
        // the "show" method to show it on the canvas.
        for (int i = 0; i < stars.length; i++) {
          stars[i].update();
          stars[i].show();
        }
        popMatrix();
        //translate(-width/2, -height);

  }
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "--present", "--window-color=#000440", "--stop-color=#FFF7F7", "plagasInvasoras" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}
