/*
   Casse Brique 

   compatible java 1.0
 
   Vincent DELLOUME

*/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;


/**
 * Un casse brique
 **/

public class CasseBrique extends Applet implements Runnable{


  final static int largJeu;
  final static int hautJeu;
  final static int largPan;


  Dimension size;                  // Taille de l'applet
  Image buffer;                    // 2eme image de l'ecran pour double-buffering
  Graphics bufferGraphics;         // A Graphics object for the buffer
  Thread animator;                 // Tache d'animation
  boolean pause;                   // Booleen pour stopper l'animation
  boolean fin;

  int nball;
  int score;
  int tempo;

  Button go,stop;
  Choice choixVitesse;
  Label lblVit;
  Label lblSco;
  Label lblBal;

//  AudioClip intro;

  int nbriq =19;

  Balle balle;
  Raquette raquette = new Raquette(50,10,30,6,true);
  Brique brique[] = new Brique[nbriq];



  /** Mise en place du 2eme ecran de double-buffering */

  public void init() {

    setLayout(null);
    addNotify();
    resize(400,400);
    go = new java.awt.Button("Go ! ");
    go.reshape(10,360,45,25);
    add(go);
    stop = new java.awt.Button("Pause");
    stop.reshape(340,360,45,25);
    add(stop);
    choixVitesse = new java.awt.Choice();
    choixVitesse.addItem("Rapide");
    choixVitesse.addItem("90 %");
    choixVitesse.addItem("80 %");
    choixVitesse.addItem("70 %");
    choixVitesse.addItem("60 %");
    choixVitesse.addItem("50 %");
    choixVitesse.addItem("40 %");
    choixVitesse.addItem("30 %");
    choixVitesse.addItem("20 %");
    choixVitesse.addItem("Lent");
    choixVitesse.reshape(120,360,70,25);
    add(choixVitesse);
    lblVit = new java.awt.Label("Vitesse");
    lblVit.reshape(70,360,40,25);
    add(lblVit);
    lblSco = new java.awt.Label();
    lblSco.reshape(260,360,90,25);
    add(lblSco);
    lblBal = new java.awt.Label("OOO");
    lblBal.reshape(220,360,40,25);
    add(lblBal);

    fin=false;
    tempo=9;
    choixVitesse.select(3);
    nball=4;
    score=0;
    lblSco.setText("Score: "+score);



    size = this.size();
    buffer = this.createImage(size.width, size.height);
    bufferGraphics = buffer.getGraphics();
    raquette.y=size.height-70;
    initmur();
    initballe();
 //   intro = this.getAudioClip(this.getDocumentBase(),"introon.au");
 //   intro.play();
  }

  public void initmur() {
    for(int i=0; i<nbriq/2; i++)
      brique[i] =new Brique((int)((0.5+i)*size.width/(nbriq/2)),80,size.width/(nbriq/2+2),20,true);
    for(int i=nbriq/2; i<nbriq; i++)
      brique[i] =new Brique((int)((0.5+i-nbriq/2)*size.width/(nbriq-nbriq/2)),40,size.width/(nbriq-nbriq/2+2),20,true);
  }

  public void initballe() {
    balle = new Balle(150,100,6,true);
    nball--;
    if (nball==3) lblBal.setText("OOO");
    if (nball==2) lblBal.setText("OO.");
    if (nball==1) lblBal.setText("O..");
    if (nball==0) lblBal.setText("...");
    if (nball<0) {
      fin=true;
    }
  }


  /** Trace des elements */

  public void paint(Graphics g) {

    bufferGraphics.setColor(Color.white);
    bufferGraphics.fillRect(0, 0, size.width, size.height);
    raquette.affiche(bufferGraphics);
    balle.affiche(bufferGraphics);
    for(int i=0; i<nbriq; i++)
      brique[i].affiche(bufferGraphics);


    g.drawImage(buffer, 0, 0, this);

  }



  public void update(Graphics g) { paint(g); }


  /** Tache d'animation */

  public void run() {

    while(!pause&!fin) {


      // Gestion de la collision balle/raquette
      raquette.collision(balle);

      // Gestion de la collision balle/brique
      for(int i=0; i<nbriq; i++)
        if (brique[i].collision(balle)) {
          if (brique[i].actif) score++;
          else score +=5;
          lblSco.setText("Score: "+score);
          if (score%152==0)
          {
            initmur();
            if (raquette.larg>=6) raquette.larg-=3;
            initballe();
          }
        }

      // Deplacament de la balle
      if (balle.deplace(size)) initballe();

      repaint(0,0,size.width,size.height);

      // Pause avant affichage de l'image suivante

      try { Thread.sleep(tempo); } catch (InterruptedException e) { ; }

    }

    animator = null;

  }



  /** Demarrage de l'animation */

  public void start() {

    if (animator == null) {
      pause = false;
      animator = new Thread(this);
      animator.start();
    }

  }



  /** Arret de l'animation */

  public void stop() { pause = true; }



  public boolean action(Event e, Object arg) {
    if (e.target == choixVitesse) {
      tempo = 3*(1+choixVitesse.getSelectedIndex())-2;
    }
    if (e.target == go) {
      fin=false;
      start();
      score=0;
      lblSco.setText("Score: "+score);
      nball=4;
      initmur();
      initballe();
    }
    if (e.target == stop) {
      if (animator != null) {
      stop.setLabel(" OK ");
      pause = true;
      }
        else
      {
      stop.setLabel("Pause");
      start();
      }
    }


    return super.action(e, arg);

  }

  // Deplace la raquette avec la souris
  public boolean mouseMove(Event e, int x, int y) {

    raquette.x=x;
    return true;

    }
  public boolean mouseDown(Event e, int x, int y) {

    pause=false;
    stop.setLabel("Pause");
    start();
    return true;

    }
 }

 class Brique
{
  int x;
  int y;
  int larg;
  int haut;
  boolean actif;
  Color couleur = new Color(0,255,0);

  Brique(int px, int py,int plarg, int phaut, boolean pactif) {
   x=px;
   y=py;
   larg=plarg;
   haut=phaut;
   actif=pactif;
  }

  Brique() {
   this(0,0,0,0,false);
  }

  boolean collision(Balle balle) {
   if (actif)
    if ((balle.x + balle.dx > x - larg/2 - balle.r)
     && (balle.x + balle.dx < x + larg/2 + balle.r)
     && (balle.y + balle.dy > y - haut/2 - balle.r)
     && (balle.y + balle.dy < y + haut/2 + balle.r))
    {
      balle.dy=-balle.dy;
      if ((balle.x + balle.dx > x - larg/2 - balle.r)
       && (balle.x + balle.dx < x + larg/2 + balle.r)
       && (balle.y > y - haut/2 - balle.r)
       && (balle.y < y + haut/2 + balle.r))
      {
        balle.dy=-balle.dy;
        balle.dx=-balle.dx;
      }
      if (larg>0) larg-=4;
      if (haut>0) haut-=4;
      if ((larg<5)||(haut<5))      actif=false;

      return true;
    }
   else
    return false;
  else
   return false;
  }


  void affiche(Graphics buff ) {
    if (actif) {
      buff.setColor(couleur);
      buff.fill3DRect(x-larg/2, y-haut/2,larg,haut,true );

    }
  }
}


class Balle
{
  int x;
  int y;
  int r;
  boolean actif;
  int dx=5;
  int dy=5;
  int dxmax=8;
  int dymax=8;

  Balle(int px, int py,int pr, boolean pactif) {
   x=px;
   y=py;
   r=pr;
   actif=pactif;
  }

  Balle() {
   this(0,0,0,false);
  }

  void affiche(Graphics buff ) {
    buff.setColor(Color.red);
    buff.fillOval(x-r, y-r, r*2, r*2);
  }

  boolean deplace(Dimension size) {
    x+=dx;
    y+=dy;
    if (y + r + dy > size.height-50) return true;
    else {
      if ((x - r + dx < 0) || (x + r + dx > size.width))  dx = -dx;
      if (y - r + dy < 0) dy = -dy;
      return false;
    }
  }

}

class Raquette
{
  int x;
  int y;
  int larg;
  int haut;
  boolean actif;

  Raquette(int px, int py,int plarg, int phaut, boolean pactif) {
   x=px;
   y=py;
   larg=plarg;
   haut=phaut;
   actif=pactif;
  }

  Raquette() {
   this(0,0,0,0,false);
  }

  boolean collision(Balle balle) {
   if ((balle.x + balle.dx > x - larg/2 - balle.r)
    && (balle.x + balle.dx < x + larg/2 + balle.r)
    && (balle.y + balle.dy > y - haut/2 - balle.r)
    && (balle.y + balle.dy < y - haut/2 + balle.r))
      {
        balle.dx=balle.dxmax*(balle.x-x)/larg;
        balle.dy=-balle.dy;
        return true;
      }
   else
    return false;
  }


  void affiche(Graphics buff ) {
    buff.setColor(Color.blue);
    buff.fill3DRect(x-larg/2, y-haut/2,larg,haut,true );
  }

}




