import java.applet.*;	//  imports Java Applet Package
import java.awt.*;	//  imports Java Abstract Window Toolkit Package for GUIs 
import java.awt.event.*;   //  event library

public class BallGame extends Applet implements Runnable, MouseListener, MouseMotionListener{
//  BallGame class extends Applet

  private Thread myThread;  //  applet thread

  private int count;
  private int ballchange;
  private int batchange;

  private int score; 
  private int random;
  private int ballsleft;		//  declare ints score, ballsleft


  private boolean running=false;     	//  set running as true
  private boolean dragbat=true;    	//  set batdrag as false  
  private boolean anotherball=true;

  private Image dbImage;     // for double buffering
  private Graphics dbg;         // for double buffering

  private Image classic;
  private Image aquarium;
  private Image fairy;
  private Image finalfantasy;
  private Image flyingdaggers;
  private Image rollercoaster;
  private Image saviour;
  private Image thisisfun;
  private Image twintowers;
  private Image wondergirl;

  public Image ball;
  private Image ball1;
  private Image ball2;
  private Image ball3;

  public Image bat;
  private Image bat1;
  private Image bat2;

  public Ball myBall;  	//  create one instance of Ball class
  public Bat myBat;  

 
 public void init()	//  initialises applet
  {

     myBall= new Ball(600, 400, 30, 110, 7, 6, 8, ball);  //  creates new Ball object from Ball class
     myBat= new Bat(600, 400, 4, 32, bat);   	//  creates new Bat object from Bat class
     this.addMouseListener(this);		//  for bat movement
     this.addMouseMotionListener(this);	//  for bat movement

classic= getImage(getCodeBase (),"classic.gif");
aquarium = getImage(getCodeBase (), "aquarium.gif");
fairy= getImage(getCodeBase (), "fairy.gif");
finalfantasy= getImage(getCodeBase (), "finalfantasy.gif");
flyingdaggers= getImage(getCodeBase (),"flyingdaggers.gif");
rollercoaster= getImage(getCodeBase (), "rollercoaster.gif");
saviour= getImage(getCodeBase (), "saviour.gif");
thisisfun= getImage(getCodeBase (),"thisisfun.gif");
twintowers= getImage(getCodeBase (),"twintowers.gif");
wondergirl= getImage(getCodeBase (), "wondergirl.gif");


myBall.ball= getImage(getCodeBase (), "ball1.gif");
ball1= getImage(getCodeBase (), "ball2.gif");
ball2= getImage(getCodeBase (), "ball3.gif");
ball3= getImage(getCodeBase (), "ball4.gif");

myBat.bat= getImage(getCodeBase (), "bat1.gif");
bat1= getImage(getCodeBase (), "bat2.gif");
bat2= getImage(getCodeBase (), "bat3.gif");

}  //  end of init() method  


public void startGame(Graphics g)
{
if (running==false)
{
Font f = new Font("Comic Sans MS", Font.BOLD, 28);
g.setFont(f);     
g.setColor(Color.red); 		//  set colour to red
g.drawString("Click in Game Area to Play" , 90, 210);  
}
}   //  end of startGame(g) method


public void loadGraphics(Graphics g)
 {

if (count==1)
{
g.drawImage(aquarium, 0, 0, this);
}

if (count==2)
{
g.drawImage(fairy, 0, 0, this);
}

if (count==3)
{
g.drawImage(finalfantasy, 0, 0, this);
}

if (count==4)
{
g.drawImage(flyingdaggers, 0, 0, this);
}		

if (count==5)
{
g.drawImage(rollercoaster, 0, 0, this);
}

if (count==6)
{
g.drawImage(saviour, 0, 0, this);
}

if (count==7)
{
g.drawImage(thisisfun, 0, 0, this);
}

if (count==8)
{
g.drawImage(twintowers, 0, 0, this);
}
if (count==9)
{
g.drawImage(wondergirl, 0, 0, this);
}
repaint();
}


public void ballbat(Graphics g)
{
if (ballchange==1)
{
g.drawImage(ball1, myBall.x, myBall.y, this);
}

if (ballchange==2)
{
g.drawImage(ball2, myBall.x, myBall.y, this);
}

if (ballchange==3)
{
g.drawImage(ball3, myBall.x, myBall.y, this);
}

if (batchange==1)
{
g.drawImage(bat1, myBat.x, myBat.y, this);// steve this works at top left corner
}

if (batchange==2)
{
g.drawImage(bat2, myBat.x, myBat.y, this);
}
repaint();
}  //  end of ballbat(g) method

 
public void start()    //  method called when applet entered
  {
    if (myThread == null)
    {
     myThread = new Thread (this);
     myThread.start();
    } 
  }

  
public void stop()    //  method called when leaving applet
  {
    if (myThread != null)
    {
     myThread.stop();
     myThread = null;
    } 
  }

 
 public void run() 	//  run method for Runnable interface
  {
   while(running==false)
{
myBall.x=myBall.x;
myBall.y=myBall.y;
}

while(running == true)
{
try {myThread.sleep(15);}	//  sleep for 15 milliseconds
catch (Exception e) { }

myBall.ballMove();		//  calls the ball's move() method
batandball();    			//  calls the batandball() method
missedball();			//  calls the missedball() method
hitWall();				//  calls the hitWall() method
restart();				//  call the restart() method 

}   // end of second while loop
}  // end of run() method


//  update method implements double buffering
public void update (Graphics g) 
  { 
// initialize buffer 
    if (dbImage == null)
    { 
      dbImage = createImage (this.getSize().width, this.getSize().height); 
      dbg = dbImage.getGraphics ();
    }
// clear screen in background 
    dbg.setColor (getBackground ());
    dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
    
// draw elements in background 
    dbg.setColor (getForeground());
    paint (dbg); 

// draw image on the screen 
    g.drawImage (dbImage, 0, 0, this); 

  }  //  end of update method


public void paint(Graphics g)	//  invokes BallGame paint method
{
g.drawImage(classic, 0, 0, this);	//  displays initial background

loadGraphics(g);		//  can display different backgrounds
myBall.ballPaint(g);		//  calls the ball's paint method
myBat.batPaint(g);		//  calls the bat's paint method
ballbat(g);  			//  can display different balls and bats   
startGame(g); 		//  displays click to play game message
showScore(g);		//  displays score and balls left
repaint();

}    //  end of paint method



public void batandball()  //  missed ball method
{

//  detect whether ball hits bat
if((myBall.x>=myBat.x-myBall.dia) && (myBall.y>=myBat.y-myBall.dia) && (myBall.y<=myBat.y+myBat.batheight))
{  

//  if ball hits the bat increase the score by 1
//  make ball appear to bounce of the bat by reversing (reverse increments dx
//  and dy) the direction of ball 
score++;

myBall.dx=-myBall.dx;
myBall.x+=myBall.dx;

// detect whether ball hits top third of bat
if (myBall.y<=myBat.y+myBat.batheight/3)
{
	random=(int)((Math.random()*2)+1);
	myBall.dy-=random;
}

// detect whether ball hits the centre third of bat
if(myBall.y>=(myBat.y+(myBat.batheight/3))&&(myBall.y<=(myBat.y+(myBat.batheight/3)*2)))
{
random=(int)((Math.random()*2)+1);
random-=1;
myBall.dy-=random;
}

// detect whether ball hits bottom third of bat
if (myBall.y>=(myBat.y+(myBat.batheight/3)*2))
{
random=(int)((Math.random()*2)+1);
myBall.dy+=random;
}
}
}  //  end of batandBall method


public void missedball()  //  missedball method
{


if ((myBall.x>=myBat.x-myBall.dia+15))
   {
//  if ball exceeds bat plus 15 pixels

running=false;
ballsleft--;

if (ballsleft>0)
{
anotherball=true;
}

else
{
anotherball=false;
myBall= new Ball(600, 400, 30, 110, 7, 6, 8, ball); 
myBall.ball= getImage(getCodeBase (), "ball1.gif");
run();
}
}  //  end of if statement detecting if ball passes bat
}  //  end of missedball method



public void hitWall()
{
if(myBall.x<11)  //  the ball hits the wall 
{
myBall.dx+=2;
myBall.dy+=1;
}
}  //  end of hitWall() method


public void restart()

//  method of restarting
{
if (running==false && anotherball==true)
{ 
running=true;
//  new ball
myBall= new Ball(600, 400, 30, 110, 7, 6, 8, ball); 
myBall.ball= getImage(getCodeBase (), "ball1.gif");
}
}  //  end of restart() method 


public void showScore(Graphics g)  
//  displays - the score and the number of balls left
{

//  set up font type and size
Font f = new Font("Comic Sans MS", Font.BOLD, 16);
g.setFont(f);     

//  set colour to blue
g.setColor(Color.blue); 		

//  display score at x=20, y=80
g.drawString("Score: " + score, 20,80);  

//  display balls left at x=20, y=100	
g.drawString("Balls left: " + ballsleft, 20,100);  

}  //  end of showScore method


public void mouseClicked(MouseEvent e)
{
//  if the mouse clicked here start the game running
if ((running==false) && ((e.getX()>=10) && (e.getX()<=600)) && ((e.getY()>=60) && (e.getY()<=340)))
 { 
running=true;
score=0;
ballsleft=3;
}

//  defines the area of the up button for background selection
if (((e.getX()>=182) && (e.getX()<=210)) && ((e.getY()>364) && (e.getY()<=386)))
{
count++;	//  variable count increased by 1
}

//  defines the area of the down button for background selection
if (((e.getX()>=394) && (e.getX()<=416)) && ((e.getY()>364) && (e.getY()<=386)))
{ 
count--; 	//  variable count increased by 1
}

//if (count>9)
//{
//count =1;
//}

//  defines the area of the up button for ball selection
if (((e.getX()>=4) && (e.getX()<=30)) && ((e.getY()>364) && (e.getY()<=386)))
{ 
ballchange++;	 //  variable ballchange increased by 1
}

//  defines the area of the down button for ball selection
if (((e.getX()>=121) && (e.getX()<=142)) && ((e.getY()>364) && (e.getY()<=386)))
{ 
ballchange--;	//  variable ballchange decreased by 1
}

//if (ballchange>3)
//{
//count =1;
//}


//  defines the area of the up button for ball selection
if (((e.getX()>=452) && (e.getX()<=476)) && ((e.getY()>364) && (e.getY()<=386)))
{ 
batchange++; 	//  variable batchange increased by 1
}


//  defines the area of the down button for ball selection
if (((e.getX()>=570) && (e.getX()<=592)) && ((e.getY()>364) && (e.getY()<=386)))
{ 
 batchange--; 	//  variable batchange decreased by 1
}

//if (batchange>2)
//{
//count =1;
//}

}  // end of mouseClicked(MouseEvent e) 


public void mouseMoved(MouseEvent e)
//  enables bat to move when the mouse is moved 

{
if (dragbat==true)  //  boolean variable dragbat set to true
    {
     myBat.y=(e.getY()-myBat.batwidth/2);
     myBat.batMove();	//  batMove() method called from Bat class  
}  //  end of if statement

}  //  end of mouseMoved(MouseEvent e)


public void mouseDragged(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}


}  //  end of BallGame class


