
/*
   SpaceWar
   Burton Rosenberg
   Thu Jul 10 16:34:42 EDT 1997

   version 2
   Fri Jul 11 10:28:02 EDT 1997
*/

package SpaceWar ;
import java.applet.* ;
import java.awt.* ;

public class SpaceWarTest3 extends Applet {

    SpaceCanvas sc ;
    SpaceEngine se ;
    Scrollbar directionControl ;
    Button boosterControl ;
    Label speedometer ;
    Label heading ;

    final static int SCROLLBAR_MIN = -180 ;
    final static int SCROLLBAR_MAX = 540 ;
    final static int INITIAL_HEADING = 180 ;
    int spacecraftDirection = INITIAL_HEADING ;
    boolean booster = false ;

    public void init() {
        
        sc = new SpaceCanvas() ;
        se = new SpaceEngine(sc) ;
        sc.addObservant(se) ;

        Panel controlPanel ;
        Panel leftPanel ;
        Panel rightPanel ;
        Panel centerPanel ;
        setLayout(new BorderLayout()) ;
        add("Center", sc ) ;
        add("South", controlPanel = new Panel() ) ;
        controlPanel.setLayout(new GridLayout(0,2)) ;
        controlPanel.add( leftPanel = new Panel() ) ;
        controlPanel.add( rightPanel = new Panel() ) ;
        leftPanel.setLayout(new BorderLayout()) ;
        leftPanel.add( "South", directionControl = new Scrollbar( 
                      Scrollbar.HORIZONTAL, 
                      INITIAL_HEADING, 1, 
                      SCROLLBAR_MIN, SCROLLBAR_MAX )) ;
        leftPanel.add( "Center", centerPanel = new Panel() ) ;
        centerPanel.add( speedometer = new Label("Velocity = 0.000") ) ;
        centerPanel.add( heading = 
                         new Label("Heading = " + INITIAL_HEADING ) ) ;
        
        rightPanel.setLayout(new GridLayout(0,5)) ;
        rightPanel.add( new Label("") ) ;
        rightPanel.add( new Label("") ) ;
        rightPanel.add( boosterControl = new Button("Booster") ) ;

        se.setSpacecraftDirection(INITIAL_HEADING) ;
        se.setBooster(booster) ;
        validate() ;

    }

    public void start() {
        se.start() ;
    }

    public void stop() {
        se.stop() ;
    }

    public boolean handleEvent(Event e) {
        if ( e.target == directionControl ) {
             spacecraftDirection = directionControl.getValue() ;
             se.setSpacecraftDirection(spacecraftDirection) ;
             heading.setText( "Heading = " + spacecraftDirection ) ;
             //heading.repaint() ;
             return true ; 
        }
        if ( e.target == boosterControl && e.id == Event.ACTION_EVENT ) {
             booster = ! booster ;
             se.setBooster( booster ) ;
             return true ;
         }
         return super.handleEvent(e) ;
    }              

}

class SpaceCanvas extends Canvas {

    double spacecraftDirection = 0.0 ;
    boolean boosterOnOff = false ;

    SpaceEngine observant ;

    // the spacecraft model
    private final static double SCALE = 5.0 ;
    private final static int spacecraftN = 4 ;
    private final static double [] spacecraftX = 
        { SCALE * 0.0, SCALE * -2.0, SCALE * 0.0, SCALE * 2.0 } ;
    private final static double [] spacecraftY = 
        { SCALE * 4.0, SCALE * -2.0, SCALE * -1.0, SCALE * -2.0 } ;
    private final static Color SPACECRAFT_COLOR = Color.blue ;

    // the booster model
    private final static int boosterN = 6 ; // must be even
    private final static double [] boosterX = 
        { SCALE * -0.2, SCALE * -0.6, 
          SCALE * 0.0, SCALE * -0.0, 
          SCALE * 0.2, SCALE *0.6 } ;
    private final static double [] boosterY = 
        { SCALE * -2.0, SCALE * -5.0, 
          SCALE * -2.0, SCALE * -5.5,
          SCALE * -2.0, SCALE * -5.0 } ;
    private final static Color BOOSTER_COLOR = Color.red ;


    SpaceCanvas() {
        setBackground(Color.black) ; 
    }

    public void addObservant(SpaceEngine se ) {
        observant = se ;
    }

    // create temporary arrays once for all
    private int [] scX = new int[spacecraftN] ;
    private int [] scY = new int[spacecraftN] ;

    public void paint(Graphics gc) {
         Dimension d = size() ;

         // note synchronized access to spacecraftDirection
         double heading = observant.getSpacecraftDirection() ;

         double a = Math.cos(heading) ;
         double b = Math.sin(heading) ;
         double xt = observant.getCoordinateX() * ((double) d.width) ;
         double yt = (1.0 - observant.getCoordinateY()) 
                     * ((double) d.height) ;
         for ( int i=0; i<spacecraftN; i++ ) {
            scX[i] = (int)(a * spacecraftX[i] - b * spacecraftY[i] + xt) ;
            scY[i] = (int)(b * spacecraftX[i] + a * spacecraftY[i] + yt) ;
         }
         gc.setColor( SPACECRAFT_COLOR ) ;
         gc.fillPolygon( scX, scY, spacecraftN ) ;

         int boX1, boX2, boY1, boY2 ;
         if ( observant.getBooster() ) {
            // booster is on 
            gc.setColor( BOOSTER_COLOR ) ;
            for ( int i=0; i<boosterN; i+=2 ) {
               boX1 = (int)(a * boosterX[i] - b * boosterY[i] + xt) ;
               boY1 = (int)(b * boosterX[i] + a * boosterY[i] + yt) ;
               boX2 = (int)(a * boosterX[i+1] - b * boosterY[i+1] + xt) ;
               boY2 = (int)(b * boosterX[i+1] + a * boosterY[i+1] + yt) ;
               gc.drawLine( boX1, boY1, boX2, boY2 ) ;
            }
         } 
         

    }

}

class SpaceEngine extends Thread {

    SpaceCanvas sc ;
    double spacecraftDirection ;
    boolean boosterOnOff ;
    double spacecraftX = 0.5 ;
    double spacecraftY = 0.5 ;
    double velocityX = 0.0 ;
    double velocityY = 0.0 ;

    SpaceEngine(SpaceCanvas sc) {
        this.sc = sc ;
    }

    synchronized public void 
    setSpacecraftDirection(int dir) {
        this.spacecraftDirection = Math.PI*((double)dir)/180.0 ;

        sc.repaint() ;
    }

    synchronized public double
    getSpacecraftDirection() { return spacecraftDirection ; } 

    synchronized public void 
    setBooster(boolean b) {
        this.boosterOnOff = b ;
        sc.repaint() ;
    }
 
    synchronized public boolean 
    getBooster() { return boosterOnOff ; }

    synchronized public void
    setCoordinates(double x, double y) {
        spacecraftX = x ;
        spacecraftY = y ;
        sc.repaint() ;
    }
 
    synchronized public double
    getCoordinateX() {
        return spacecraftX ;
    }

    synchronized public double
    getCoordinateY() {
        return spacecraftY ;
    }
   
    private final static double K = 0.0001 ;

    public void run() {
        while(true) {
	    //System.out.println("run..") ;
	    try {

		Thread.sleep(20) ;

                if ( getBooster() ) {
                   double heading = getSpacecraftDirection() ;
                   velocityX += - K * Math.sin(heading) ;
                   velocityY += - K * Math.cos(heading) ;
                }

                spacecraftX += velocityX ;
                spacecraftX = spacecraftX - Math.floor(spacecraftX) ;
                spacecraftY += velocityY ;
                spacecraftY = spacecraftY - Math.floor(spacecraftY) ;
                setCoordinates( spacecraftX, spacecraftY ) ;
//System.out.println(spacecraftX) ;

	    } catch ( InterruptedException ie ) { }
        }
    }
}
