//Nathan Swem
//April 27, 1998
//Final project, car racing game.

import java.applet.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class proj extends Applet implements ActionListener
{
   private carCanvas c1, c2;
   private playerFrame p1, p2;
   private Button setp1, setp2, start, reset, directions;
   private Panel playerPanel;
   private TextField t;
   Image flag1, flag2, Ferrari, Lotus, Lambo, Ferrari4, NSX, Ferrari5, buffer1;
   private Graphics gContext1;
   private int pint1 = 1, car1x = 0, car2x = 0;
   private int pint2 = 2, tac1 = 44, tac2 = 44, turn = 1;
   private dir d;
   private AudioClip engine, song1, song2;
   double i = (double) (Math.PI);
   int x1t, y1t, x2t, y2t;

   int x1 = (int) ( 147 + ( 100*( Math.cos(Math.PI))) );
   int y1 = (int) ( 350 + ( 100*( Math.sin(Math.PI))) );

   int x2 = (int) ( 447 + ( 100*( Math.cos(Math.PI))) );
   int y2 = (int) ( 350 + ( 100*( Math.sin(Math.PI))) );

   private boolean s1 = false, s2 = false, turn1 = true;

   public void init()
   {
      engine = getAudioClip( getDocumentBase(), "car.au" );
      song1 = getAudioClip( getDocumentBase(), "music1.au" );
      song2 = getAudioClip( getDocumentBase(), "music2.au" );

      Ferrari = getImage( getDocumentBase(), "355sd.gif" );
      Lotus = getImage( getDocumentBase(), "Espritsd.jpg" );
      Lambo = getImage( getDocumentBase(), "lambosd.jpg" );
      Ferrari4 = getImage( getDocumentBase(), "F40sider.jpg" );
      NSX = getImage( getDocumentBase(), "NSXsdb.jpg" );
      Ferrari5 = getImage( getDocumentBase(), "512sd.gif" );
      flag1 = getImage( getDocumentBase(), "Flag1.jpg" );
      flag2 = getImage( getDocumentBase(), "Flag2.jpg" );

      buffer1 = createImage( 120, 65 );
      gContext1 = buffer1.getGraphics();
      gContext1.setColor( Color.yellow );

      p2 = new playerFrame( Ferrari, Lotus, Lambo, Ferrari4, NSX, Ferrari5, pint2 );
      p2.setSize(660, 200);
      p2.setVisible( true );

      p1 = new playerFrame( Ferrari, Lotus, Lambo, Ferrari4, NSX, Ferrari5, pint1 );
      p1.setSize(660, 200);
      p1.setVisible( true );
      
      c1 = new carCanvas( p1.i, flag1, flag2, 1, buffer1, gContext1, song2 );
      c1.setBackground( Color.yellow );
      c1.setSize( 620, 65 );
      c1.setLocation(0, 95 );
      add( c1 );

      c2 = new carCanvas( p2.i, flag1, flag2, 2, buffer1, gContext1, song2 );
      c2.setBackground( Color.yellow );
      c2.setSize( 620, 65 );
      c2.setLocation(0, 185 );
      add( c2 );

      d = new dir();
      d.setSize(370, 200);
      d.setLocation( 200, 200 );
      d.setVisible( false );

      playerPanel = new Panel();
      playerPanel.setLayout( new GridLayout( 1, 2 ));

      setp1 = new Button( "Player One Shift" );
      setp1.addActionListener( this );
      playerPanel.add( setp1 );

      setLayout( null);

      setp2 = new Button( "Player Two Shift" );
      setp2.addActionListener( this );
      playerPanel.add( setp2 );

      add( playerPanel );     
      playerPanel.setBounds(0, 360, 600, 20 );

      t = new TextField( "Swem's Performance Car Challenge" );
      t.setFont( new Font( "TimesRoman", Font.BOLD + Font.ITALIC, 22 ));
      add( t );
      t.setBounds(50, 0, 400, 35 );

      start = new Button( "Begin Game" );
      start.addActionListener( this );
      add( start );
      start.setBounds( 160, 160, 100, 25 );

      reset = new Button( "Reset" );
      reset.addActionListener( this );
      add( reset );
      reset.setBounds( 340, 160, 40, 25 );

      directions = new Button( "Directions" );
      directions.addActionListener( this );
      add( directions );
      directions.setBounds( 260, 160, 80, 25 );

      setSize( 600, 385 );
   }


   public void paint( Graphics g )
   {
      g.drawLine( 559, 50, 559, 270 );

      g.drawString("Player 1", 0, 93);
      g.drawString("Player 2", 0, 183);
      g.drawString("Finish", 560, 93);
      g.drawArc(50, 250, 190, 180, 60, 180 );
      g.drawArc(350, 250, 190, 180, 60, 180 );

      g.fillArc(145, 350, 10, 10, 0, 180 );
      g.fillArc(445, 350, 10, 10, 0, 180 );

      g.setColor( Color.red );

      g.drawArc(50, 250, 190, 180, 0, 60);
      g.drawArc(350, 250, 190, 180, 0, 60);

      if( s1 && i >= Math.PI && i <= 2 * Math.PI )
      {         
         g.setColor( Color.white );
         x1t = (int) ( 150 + ( 100*( Math.cos(i-.05))) );
         y1t = (int) ( 350 + ( 100*( Math.sin(i-.05))) );

         g.drawLine( 150, 350, x1t, y1t );
         
         g.setColor( Color.red);
         x1 = (int) ( 150 + ( 100*( Math.cos(i))) );
         y1 = (int) ( 350 + ( 100*( Math.sin(i))) );

         g.drawLine( 150, 350, x1, y1 );

         try{ Thread.sleep( (tac1) ); }
         catch( InterruptedException r ) {}

         i = i + .05;

         repaint();         
      }

      g.setColor( Color.white );
      g.drawLine( 450, 350, x2, y2 );

      if(x1 > 195)
         car1x = 0;
      else
      {
         car1x =  x1 - 50;
      }

      if( s2 && i >= Math.PI && i <= 2 * Math.PI )
      {         
         g.setColor( Color.white );
         x2t = (int) ( 450 + ( 100*( Math.cos(i-.05))) );
         y2t = (int) ( 350 + ( 100*( Math.sin(i-.05))) );

         g.drawLine( 450, 350, x2t, y2t );

         g.setColor( Color.red );
         x2 = (int) ( 450 + ( 100*( Math.cos(i))) );
         y2 = (int) ( 350 + ( 100*( Math.sin(i))) );

         g.drawLine( 450, 350, x2, y2 );

         try{ Thread.sleep( (tac1) ); }
         catch( InterruptedException q ) {}

         i = i + .05;

         repaint();         
      }

      g.setColor( Color.white );
      g.drawLine( 150, 350, x1, y1 );

      if(x2 > 495)
         car2x = 0;
      else
      {
         car2x =  x2 - 350;
      }
   }

   public void actionPerformed( ActionEvent e )
   {
      if( e.getSource() == setp1 )
      {
         if ( turn1 )
         {
            s1 = !s1;
            i = Math.PI;
            repaint();
            tac1 = tac1 - 2;
            engine.play();
            song1.stop();
            if( s1 == false )
            {
               c1.car = p1.i;
               c1.tempx1 = (int ) (car1x / 1.5 );
               c1.t1++;
               c2.t1++;
               c2.tempx2 = (int ) (car1x / 1.5 );
                             
               c1.repaint();
               c2.repaint();
               
               turn1 = false;
               engine.stop();
            }
         }
      }

      if( e.getSource() == setp2 )
      {
         if( turn1 == false )
         {
            s2 = !s2;
            i = Math.PI;
            repaint();
            tac2 = tac2 - 2;
            song1.stop();
            engine.play();

            if( s2 == false )
            {
               c2.car = p2.i;
               c1.tempx2 = (int ) (car2x / 1.5 );
               c1.t2++;
               c2.t2++;
               c2.tempx1 = (int ) (car2x / 1.5 );
               
               c1.repaint();
               c2.repaint();
             
               turn1 = true;
               engine.stop();
            }
         }
      }

      if( e.getSource() == reset )
      {
         turn = 0;
         c1.x1 = c1.x2 = c1.tempx1 = c1.tempx2 = c1.t1 = c1.t2 = c1.i = 0;
         c2.x1 = c2.x2 = c2.tempx1 = c2.tempx2 = c2.t1 = c2.t2 = c2.i = 0;

         tac1 = tac2 = 44;

         turn1 = true;
         s1 = s2 = false;

         c1.reset = 2;
         c2.reset = 2;

         c1.repaint();
         c2.repaint();

         p2.setVisible( true );
         p1.setVisible( true );
      }

      if( e.getSource() == directions)
      {
         d.setVisible( true );
      }

      if( e.getSource() == start )
      {
         c1.reset = 0;
         c2.reset = 0;

         c1.car = p1.i;
         c2.car = p2.i;

         c1.repaint();
         c2.repaint();
         song1.play();
      }

   }

   public void update( Graphics g) { paint( g ); }
}


class carCanvas extends Canvas
{
   Image car, flag1, flag2;
   int x1 = 0, x2 = 0, tempx1 = 0, tempx2 = 0, i = 0;
   int player, t1 = 0, t2 = 0, reset = 0;
   private Graphics gContext;
   private Image buffer;
   private AudioClip bad;

   public carCanvas( Image c, Image f1, Image f2, int p, Image a, Graphics q, AudioClip s ) 
   {
      car = c;    
      player = p;
      flag1 = f1;
      flag2 = f2;
      buffer = a;
      gContext = q;
      bad = s;
   }

   public void start()
   {
      gContext.drawImage( car, 0, 0, this );
   }

   public void paint( Graphics g )
   {
      if( reset == 2 )
      {
         g.setColor( Color.yellow );
         g.fillRect( 0, 0, 600, 65 );
      }


      else if( i < (x1 + tempx1) && x1 < 559 )
      {
         g.drawImage( buffer, i, 0, 120, 65, this );

         gContext.fillRect( 0, 0, 1, 65 );

         g.drawImage( buffer, i-1 , 0, 120, 65, this );

         gContext.drawImage( car, 0, 0, this );
         
         try{ Thread.sleep( 5 ); }
         catch( InterruptedException j ) {}
         i = i + 1;

         repaint();
      }

      else if( i > 559 && t2 == t1 && i > x2 )
      {
         g.setColor( Color.yellow );

         gContext.fillRect( 0, 0, 120, 65 );

         g.drawImage( buffer, 0 , 0, 600, 65, this );       

         g.drawImage( flag1, 0, 0, 65, 65, this );
         g.drawImage( flag2, 65, 0, 65, 65, this );
         g.drawImage( flag1, 130, 0, 65, 65, this );
         g.drawImage( flag2, 195, 0, 65, 65, this );
         g.drawImage( flag1, 260, 0, 65, 65, this );
         g.drawImage( flag2, 325, 0, 65, 65, this );
         g.drawImage( flag1, 390, 0, 65, 65, this );
         g.drawImage( flag2, 455, 0, 65, 65, this );
         g.drawImage( flag1, 520, 0, 65, 65, this );
         bad.play();
      }

      else
      {
         integers();
         g.drawImage( car, x1, 0, 120, 65, this );
      }
   }

   public void update( Graphics g ) { paint ( g ); }

   public void integers()
   {
      x1 = i;
      tempx1 = 0;
      x2 = tempx2 + x2;
      tempx2 = 0;
   }
}

class playerFrame extends Frame implements MouseListener, MouseMotionListener
{
   private Image Ferrari, Lotus, Lambo, F40, NSX, F50;
   private TextField t, l;
   private int pint;
   Image i;

   public playerFrame( Image f3, Image lo, Image la, Image f4, Image nsx, Image f5, int a )
   {
      Ferrari = f3;
      Lambo = la;
      Lotus = lo;
      F40 = f4;
      NSX = nsx;
      F50 = f5;
      pint = a;
      

      l = new TextField("Player " + Integer.toString( pint ) + " Please Choose Your Car:");
      l.setFont( new Font( "Serif", Font.BOLD, 16 ));
      add( l, BorderLayout.NORTH );

      t = new TextField( 60 );
      t.setEditable( false );
      add( t, BorderLayout.SOUTH );

      addWindowListener( new CloseWindow() );

      addMouseMotionListener( this );
      addMouseListener( this );
   }

   public void paint( Graphics g )
   {
      g.drawImage( Ferrari, 1, 50, 110, 70, this );
      g.drawImage( Lotus, 110, 50, 110, 90, this );
      g.drawImage( Lambo, 220, 50, 110, 75, this );
      g.drawImage( F40, 330, 50, 110, 65, this );
      g.drawImage( NSX, 440, 50, 110, 50, this );
      g.drawImage( F50, 550, 50, 110, 80, this );
   }

   public void mouseClicked( MouseEvent e )
   {
      if( e.getX() < 110 && e.getX() > 1 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Ferrari 355!!" );
         i = Ferrari;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
      if( e.getX() < 220 && e.getX() > 110 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Lotus Esprit!!" );
         i = Lotus;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
      if( e.getX() < 330 && e.getX() > 220 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Lamborghini Diablo!!" );
         i = Lambo;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
      if( e.getX() < 440 && e.getX() > 330 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Ferrari F40!!" );
         i = F40;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
      if( e.getX() < 550 && e.getX() > 440 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Acura NSX!!" );
         i = NSX;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
      if( e.getX() < 660 && e.getX() > 550 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "You Picked the Ferrari 512 Testarossa!!" );
         i = F50;
         try{ Thread.sleep( 2000 ); }
         catch( InterruptedException i ) {}
         setVisible( false );
      }
   }

   public void mouseMoved( MouseEvent e )
   {
      if( e.getX() < 110 && e.getX() > 1 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Ferrari 355" );
      }
      if( e.getX() < 220 && e.getX() > 110 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Lotus Esprit" );
      }
      if( e.getX() < 330 && e.getX() > 220 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Lamborghini Diablo" );
      }
      if( e.getX() < 440 && e.getX() > 330 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Ferrari F40" );
      }
      if( e.getX() < 550 && e.getX() > 440 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Acura NSX" );
      }
      if( e.getX() < 660 && e.getX() > 550 && e.getY() > 50 && e.getY() < 120 )
      {
         t.setText( "Ferrari 512 Testarossa" );
      }
   }

   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) {}
}

class CloseWindow extends WindowAdapter
{
   public void windowClosing( WindowEvent e )
   {
      e.getWindow().setVisible( false );
   }
}

class dir extends Frame
{
   private TextArea t;

   public dir()
   {
      String s = "Use the Player Shift buttons at the bottom" +
                 "of the screen to start and stop the tachometers." +
                 "Try and stop the tachometer as close as possible" +
                 "the redline area.  Your car will advance in" +
                 "porportion to how close the tachometer needle is" +
                 "to the redline area.  However, redlining the" +
                 "tachometer will not advance your car." +
                 "Press begin before every game.  Good Luck!";

      setLayout( new BorderLayout() );
      t = new TextArea( s, 6, 68, t.SCROLLBARS_NONE );
      t.setEditable( false );
      add( t, BorderLayout.CENTER );

      addWindowListener( new CloseWindow() );
   }

}