// One Player PING PONG.
// Coded by Santosh "TEJA" Ganti.

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.Boolean;
import java.net.URL;

 public class pong extends Applet
  implements MouseListener, MouseMotionListener, Runnable, ActionListener {

  int mouseX = 0,mouseY = 145; // coordinates of Mouse.
  int pres_x=0,pres_y=0,prev_x=0,prev_y=0;
  int dir_case=0;
  int hit=0;
  int total_hit=0;
  int delay=25;
  int sliderhit=0;
  int tempY=25;
  Thread t=null;
  boolean stop_flag=false;
  boolean hit_flag=false;
  boolean miss_flag=false;
  boolean pong_flag=true;
  boolean sliderhit_flag=false;
  boolean comphit=false;
  boolean suspend_flag=false;
  Color bg=new Color(222,243,243);      //bgcolor
  Color po=new Color(128,0,128);        //purple 
  Color oo=new Color(254,123,1);        //orange 
  Color go=new Color(0,117,58);         //green
  Color o=new Color(29,88,88);
  AudioClip click;
  AudioClip loose;
  AudioClip drip;
  AudioClip applause;
  AudioClip ding;
  String msg1="  Click  to  BEGIN   ";
  String msg2="  You  completed  15  HITS !!! Click to Begin Again ";
  String msg3="  You  LOOSE!!! Click  to TRY AGAIN! ";
  String msg="";
  Button stop;
  Button suspend;
  boolean showscore=false;
  String score="";
  public void init() {
     setLayout(null);

     stop=new Button(" Stop ");
     stop.setBounds(15,5,45,16);
     stop.setVisible(false);
     add(stop);
     stop.setActionCommand("stop");
     stop.addActionListener(this);

     suspend=new Button("Pause");
     suspend.setBounds(70,5,55,16);
     suspend.setVisible(false);
     suspend.setActionCommand("suspend");
     add(suspend);
     suspend.addActionListener(this);

     addMouseListener(this);
     addMouseMotionListener(this);
     setBackground(bg);
     setForeground(po);

     click = getAudioClip(getDocumentBase(), "click.au");
     loose = getAudioClip(getDocumentBase(), "loose.au");
     drip = getAudioClip(getDocumentBase(), "drip.au");
     applause = getAudioClip(getDocumentBase(), "applause.wav");
     ding = getAudioClip(getDocumentBase(), "ding.au");

  }
  public void initialise(){
       stop.setVisible(false);
       suspend.setLabel("Pause");
       suspend.setVisible(false);
       msg=msg1;
       hit=0;total_hit=0;sliderhit=0;
       delay=25;tempY=25;
       mouseY=145;
       miss_flag=false;
       sliderhit_flag=false;
       hit_flag=false;
       comphit=false;
       showscore=false;
       pong_flag=true;
       suspend_flag=false;
       pres_x=220;
       pres_y=140;
       prev_x=220-1;
       prev_y=140-1;
       score="";
  }
  public void start() {
       initialise();
       stop_flag=false;
  }
  public void run(){
    for( ; ; ) {
     try{
         synchronized(this){
          while(suspend_flag) {
            wait();
          }
         }
         if(total_hit<= 25){
          if(hit==7){
            hit=0;
            delay-=5;
           }
          }
         if(total_hit>25 && total_hit<=40) delay=7;
         if(total_hit>40 && total_hit<=55) delay=5;
         if(total_hit>55)  delay=3;

         calculate();
         verifyhit();

         if(hit_flag){
            total_hit++;hit++;
            if(comphit){
              drip.play();
              comphit=false;
            }
            else click.play();
            change_dir();
            hit_flag=false;
         }
         if(sliderhit_flag){
              sliderhit++;hit++;total_hit++;
              ding.play();
              score=" Score  :  "+sliderhit+" ";
              change_dir();
              repaint(318,6,65,14);
              sliderhit_flag=false;
            }
         
         if(sliderhit==15){
           showscore=false;
           applause.play();
           initialise();
           msg=msg2;
           repaint();
           stop_flag=true;
         }
         if(miss_flag) {
           loose.play();
           initialise();
           msg=msg3;
           repaint();
           stop_flag=true;
         }
         repaint(pres_x-4,pres_y-4,18,18);
         if(pres_y<238)
           repaint(4,pres_y-20,5,50);
         else if(pres_y>=238)
           repaint(4,218,5,50);
         if(stop_flag)
           break;
         Thread.sleep(delay);
     }catch (InterruptedException e){}
    }
  }
  public void stop() {
    stop_flag=true;
    t=null;
  }

  public void calculate(){
    if((pres_xprev_x)&&(pres_y>prev_y)) { 
      dir_case=2;                               
      prev_x=pres_x;
      prev_y=pres_y;
      pres_x+=2;
      pres_y+=2;
    } 
    else if((pres_xprev_y)) {
      dir_case=3;                              
      prev_x=pres_x;
      prev_y=pres_y;
      pres_x-=2;
      pres_y+=2;
    } 
    else if((pres_x>prev_x)&&(pres_y432){
         if((pres_y+2<=mouseY+23)&&(pres_y+8>=mouseY-23))
           sliderhit_flag=true;
         else miss_flag=true;
     }
     switch(dir_case){
      case 1:
             if((pres_x<8)||(pres_y<24))
                hit_flag=true;
             if((pres_x<8)&&(pres_y>=24))
                comphit=true;
             break;
      case 2:         
             if((pres_y>256)&&(pres_x<=432))
                hit_flag=true;
             break;
      case 3:
             if((pres_x<8)||(pres_y>256))
                hit_flag=true;
             if((pres_x<8)&&(pres_y<=256))
                comphit=true;
             break;
      case 4:
             if((pres_y<24)&&(pres_x<=432))
                hit_flag=true;
             break;
     }
   }
   public void change_dir(){
      switch(dir_case){
       case 1:
              prev_x=pres_x;
              prev_y=pres_y;
              if(pres_x<=4 && pres_y<=24){
               pres_x+=10;
               pres_y+=10;
              }
              if(pres_y<24){
               pres_x-=2;
               pres_y+=2;
              }
              if(pres_x<8){
               pres_x+=2;
               pres_y-=2;
              }
              break;

       case 2:              
              prev_x=pres_x;
              prev_y=pres_y;
              if(pres_x>=432 && pres_y>=256){
               pres_x-=10;
               pres_y-=10;
              }
              if(pres_y>256){
               pres_x+=2;
               pres_y-=2;
              }
              if(pres_x>432){
               pres_x-=2;
               pres_y+=2;
              }
              break;
              
       case 3:
              prev_x=pres_x;
              prev_y=pres_y;
              if(pres_x<=8 && pres_y>=256){
               pres_x+=10;
               pres_y-=10;
              }
              if(pres_x<8){
               pres_x+=2;
               pres_y+=2;
              }
              if(pres_y>256){
               pres_x-=2;
               pres_y-=2;
              }
              break;
       case 4:
              prev_x=pres_x;
              prev_y=pres_y;
              if(pres_x>432 && pres_y<24){
               pres_x-=10;
               pres_y+=10;
              }
              if(pres_x>432){
               pres_x-=2;
               pres_y-=2;
              }
              if(pres_y<24){
               pres_x+=2;
               pres_y+=2;
              }
              break;

      }
   }
   synchronized void pongresume() {
     suspend_flag=false;
     notify();
   }
   public void actionPerformed(ActionEvent ae) {
     if(ae.getActionCommand().equalsIgnoreCase("stop")) {
       stop_flag=true;
       initialise();
       repaint();
     }
     else {
      if(suspend.getLabel().equalsIgnoreCase("Pause")){
        suspend.setLabel("Resume");
        suspend_flag=true;
      }
      else if(suspend.getLabel().equalsIgnoreCase("Resume")) {
        suspend.setLabel("Pause");
        pongresume();
      }
     }
   }
   public void mouseClicked(MouseEvent me) {
    if(pong_flag){
      msg="";
      repaint(14,6,240,14);
      stop.setVisible(true);
      suspend.setVisible(true);
      showscore=true;
      score=" Score :  0";
      repaint(320,6,55,14);
      t=new Thread(this);
      t.start();
    }
    stop_flag=false;
    pong_flag=false;
   }
   public void mouseEntered(MouseEvent me) { }
   public void mouseExited(MouseEvent me) { }
   public void mousePressed(MouseEvent me) { }
   public void mouseReleased(MouseEvent me) { }
   public void mouseDragged(MouseEvent me) { }

  public void mouseMoved(MouseEvent me) {
    
    showStatus("Moving mouse at " + me.getX() + ", " + me.getY());
    mouseX = me.getX();
    mouseY = me.getY();
    if(mouseY<=20) { mouseY+=20;}  // ***shud work?****
    if(mouseY<243)
      repaint(442,20,3,250);
    else if(mouseY>=223) repaint(422,219,23,47);
  }
  public void paint(Graphics g) {

     int compx[]={5,8,8,5};
     int compy[]={pres_y-15,pres_y-18,pres_y+28,pres_y+25};
     int x[]={442,445,445,442};
     int y[]={mouseY-23,mouseY-20,mouseY+20,mouseY+23};

     g.setColor(bg);
     g.fillRect(0,0,450,270);
     g.setColor(o);
     g.fillRect(0,22,450,2);
     g.fillRect(0,266,450,4);
     g.fillRect(0,0,4,270);
     g.fillRect(446,0,4,270);
     g.fillRect(0,0,450,4);
     g.drawLine(225,22,225,270);
     g.drawString(msg,10,18);

     g.setColor(o);
     if(showscore) g.drawString(score,320,18);

     g.setColor(po);
     g.fillOval(pres_x,pres_y,10,10);

     g.setColor(oo);
     if(compy[1]<24){compy[1]=25;compy[2]=71;compy[0]=28;compy[3]=68;}
     if(compy[2]>266){compy[2]=265;compy[1]=219;compy[0]=222;compy[3]=262;}
     g.fillPolygon(compx,compy,4);

     g.setColor(Color.black);
     if(y[0]<24){y[0]=25;y[1]=28;y[2]=68;y[3]=71;}
     if(y[3]>266){y[3]=265;y[0]=219;y[1]=222;y[2]=262;}
     g.fillPolygon(x,y,4);
     g.setColor(po);
    }
}