/*
  * Kommentierter Quellcode eines
  * Applets in Java, das eine Verfolgung gemäß 
  * dem Hundekurvenproblem nach Bouguer simuliert.
  * 
  *
  * Kommentare (wie dieser) werden bei der Kompilierung nicht
  * berücksichtigt. 
  * 
  * -  Kurzkommentare werden mit dem Steuerzeichen //
  *    eingeleitet und automatisch durch den Zeilenumburch abgeschlossen.
  * -  Mehrzeilige Kommentare müssen durch Steuerzeichen eröffnet /* und
  *    abgeschlossen  * /  werden.
  */
 
 
 
 /* 
  * Die zwei Pakete  java.awt.*  und  java.applet.*  (das sind Java 
  * Klassenbibliotheken) müssen zu Beginn importiert werden; 
  * sie stellen eine gewisse Grundfunktionalität zur Verfügung. 
  */
 import java.awt.*;
 import java.applet.*;
 
 
 
 
 /* 
  * Nun Deklarieren wir eine Klasse mit dem Namen BeispielApplet.
  * Unsere Klasse soll öffentlich zugänglich sein, weshalb wir sie als
  * 'public' deklarieren und alle Eigenschaften eines Applets besitzen
  * (Ererbung der Appleteigenschaften durch den Zusatz 'extends Applet').
  * 
  * Da wir eine Verfolgung, also einen dynamischen Vorgang darstellen
  * wollen, implementieren wir zusätzlich mit dem Schlüsslewort 'implements',
  * gefolgt von 'Runnable' die Runnable-Schnittstelle. Diese macht unsere 
  * Klasse threadfähig, d.h. dem Applet wird während seiner Ausführung eine
  * betimmte Rechnerzeit zugewiesen, in der die Methoden der 
  * Klasse ausgeführt werden.
  */ 
 public class BeispielApplet extends Applet implements Runnable
 {
     /* 
      * Deklaration der Variablen und Objekte, die allen Methoden
      * der Klasse zugänglich sein sollen.
      */
 
     // Deklaration eines Offscreen-Images:
     Image im = null;
     Graphics gr = null;
     Dimension d = null;
 
     
     Thread verfolgung; // Deklaration eines Threads mit dem Namen 'verfolgung'.
     
 
     double u; // Geschwindigkeit des Ziels.
     double v; // Geschwindigkeit des Verfolgers.
 
     double xQ; // x-Koordinate des Ziels.
     double yQ; // y-Koordinate des Ziels.
     
     double xP; // x-Koordinate des Verfolgers.
     double yP; // y-Koordinate des Verfolgers.
 
     double dPQ; // aktueller Abstand des Verfolgers vom Ziel.
 
     double r; // Radius der Kreise, die die Akteure am Bildschirm repräsentieren.
 
 
 
 
 
     /*
      * Die init()-Methode wird nun deklariert und definiert.
      * Sie übernimmt die Voreinstellung von im Programm benötigten
      * Parametern. 
      */
     public void init()
     {
         /*
          * Mit dem Befehl 'add' fügen wir der Zeichenfläche
          * zwei Buttons (Objekte) hinzu, die mit 'Verfolgung' und
          * 'Reset' beschriftet werden.
          */
         add(new Button("Verfolgung")); 
         add(new Button("Reset"));       
     
         setBackground(Color.white); // Hintergrundfarbe 'weiß'.
 
         d=size(); // Appletgröße (im HTML-Text festgelegt) wird abgefragt.
         im = createImage(d.width, d.height); // Ein Offscreen-Image der
         gr = im.getGraphics();                 // selben Größe wird erzeugt.
     
         r=2.5;
 
     } 
     // Ende der init()-Methode.
     
 
 
 
 
 
 
 
 
     /*
      * Die start()-Methode wird deklariert und definiert.
      * Sie startet das Applet, nachdem es geladen und initialisiert 
      * (init()-Methode !) wurde.
      */
     public void start()
     {
         xP=100; //Startkoordinaten des Verfolgers
         yP=50;
     
         xQ=20;   //Startkoordinaten des Ziels
         yQ=220;
     
         u=2;         // vZiel=2 Pixel/Z.
         v=2.5;         // vVerfolger=2.5 Pixel/Z.
 
         repaint();  // Zeichnen der Startpositionen.
     }
     // Ende der start()-Methode.
 
 
 
 
 
 
 
     /*
      * Die stop()-Methode wird deklariert und definiert.
      * Sie wird vom Laufzeitsystem automatisch aufgerufen, wenn die
      * HTML-Seite, in der das Applet abläuft, verlassen wird.
      */
     public void stop() 
     {
         if (verfolgung!=null)         // Falls unser Thread 'verfolgung'
         {                    // gestartet und noch nicht wieder
             verfolgung.stop();        // gestoppt wurde, wird er nun gestoppt
             verfolgung=null;        // (Einsparen von Rechnerzeit).
         }                            
     }
     // Ende der stop()-Methode.
 
     
 
 
 
     /*
      * Die action()-Methode wird deklariert und definiert.
      * Diese Methode verarbeitet gewisse Benutzereingaben, in unserem
      * Fall das Anklicken eines der beiden Buttons.
      * Das Objeckt 'arg' liefert uns den Namen des angesprochenen 
      * Buttons. In der if..elseif-Anweisung wird definiert, wie das
      * Programm auf den entsprechenden Klick reagieren soll:
      */
     public boolean action(Event e, Object arg)
     {    
         if("Reset".equals(arg))  // falls der Reset-Button angeklickt wurde,
         {
             // leeren wir unsere Zeichenfläche,
             d=size();
             im = createImage(d.width,d.height);
             gr = im.getGraphics();
 
             // stoppen die Verfolgung (falls diese im Gang ist)
             if(verfolgung!=null)
             {
                 verfolgung.stop();
                 verfolgung=null;
             }
 
             // und starten von neuem.
             start();    
 
             return true; // Benutzereingabe wurde korrekt bearbeitet.
         }
 
 
         
         else if("Verfolgung".equals(arg))  // falls der Verfolgungs-Button 
         {                                   // angeklickt wurde,
             
             // fragen wir ab, ob die Verfolgung nicht evtl. schon in Gang ist
             if(verfolgung==null) // falls dies nicht der Fall ist
             {
                 verfolgung=new Thread(this); // erzeugen wir eine ThreadInstanz
                 verfolgung.start();    // und starten den Thread. Die run()-
                                     // Methode wird nun automatisch aufgerufen.
             }
 
             return true; // Benutzereingabe wurde korrekt bearbeitet.
         }
 
         return super.action(e,arg); // In dieser Methode nicht definierte 
                             // Benutzereingaben werden an höhere 
                             // Hierarchieklassen weitergeleitet.
     }
     // Ende action()-Methode.
     
 
 
 
 
 
 
     /*
      * Die run()-Methode definiert die Routine, die ein Thread
      * nach seinem Start ausführen soll. In unserem Fall wird die Verfolgung
      * gemäß dem gewöhnlichen Hundekurvenproblem simuliert.
      */
     public void run() 
     {
 
         while (true) 
         {
         
             // Der aktuelle Abstand von Ziel und Verfolger wird berechnet.
             dPQ = Math.sqrt(
                 Math.pow(xQ-xP,2) + Math.pow(yQ-yP,2)
                 );
             
             if(dPQ<r)  // Falls der Verfolger in eine hinreichende Umgebung des
             {           // Ziels eingedrungen ist, werten wir die Verfolgung als
                        // erfolgreich 
                 verfolgung.stop(); // und beenden sie.
                 verfolgung=null;
             }
 
             
             // Der Hase flüchte auf einer Geraden parallel zur x-Achse.
             xQ += u;  
     
             
             // Der Hund läuft entlang der Visierline auf den Hasen zu.
             xP += v * (xQ-xP)/dPQ;
             yP += v * (yQ-yP)/dPQ;       
         
             
             
             repaint(); // Die neu errechneten Positionen der Akteure 
                        // werden gezeichnet.
             
             
             try                     
             {                        // Der Thread wird für die Dauer von
                 Thread.sleep(100);    // 100ms in den Ruhezustand versetzt.
                                     
             }
             catch(Exception e){}                    
         }
     }
     // Ende der run()-Methode.
 
 
 
 
 
     /*
      * Die update()-Methode wird überschrieben, um einen Flimmereffekt zu
      * vermeiden.
      */
     public void update(Graphics g)
     {
         paint(g);  
     }
     // Ende der update()-Methode.
 
 
 
 
 
 
     /*
      * In der paint()-Methode wird die Bildschirmausgabe definiert.
      */
     public void paint(Graphics g) 
     {    
         // Zeichnen der aktuellen Zielposition 
         // (blauer Kreis, Durchmesser:2*r) im Offscreen-Image.
         gr.setColor(Color.blue);
         gr.fillOval((int)Math.round(xQ-r), (int)Math.round(yQ-r), (int)(2*r), (int)(2*r));
 
         // Zeichnen der aktuellen Verfolgerposition 
         // (roter Kreis, Durchmesser:2*r) im Offscreen-Image.
         gr.setColor(Color.red);
         gr.fillOval((int)Math.round(xP-r), (int)Math.round(yP-r), (int)(2*r), (int)(2*r));
     
         // 1:1 Übertragung des Offscreen-Bildes auf die Bildschirmoberfläche. 
         g.drawImage(im,0,0,d.width,d.height,this);    
     }
     // Ende der paint()-Methode.
 
 
 
 } // Ende der Klasse BeispielApplet.