// ****************************************************************************
// *                                                                          *
// *                             T U R T L E                                  *
// *                                                                          *
// ****************************************************************************
// Umsetzung des Turtle-Grafikssystems der Programmiersprache Logo. Eine Turtle
// ist eine Schildkröte. Diese Schildkröte läuft auf einer Unterlage und dabei
// hinterläßt sie eine Spur. Die Schildkröte versteht dabei eine Reihe von
// Kommandos. Somit kann mit Anweisungen an die Schildkröte gezeichnet werden.
//
// Schnittstelle
// =============
// Die Turtle bildet eine Schnittstelle die verschiedene Befehle versteht und
// somit zur Verfügung stellt. Die hier verwendeten Befehle entsprechen den
// Originalbefehlen der Ursprünglichen Turtle in der Programmiersprache Logo.
// (Mit + gekennzeichnete Methoden sind bereits implementiert)
//   + forward    Vorwärtsbewegung um eine mitgegebene Distanz.
//   + back       Rückwärtsbewegung um eine mitgegebene Distanz.
//   + turnRight  Drehung nach rechts um einen mitgegebenen Winkel.
//   + turnLeft   Drehung nach links um einen mitgegebenen Winkel.
//   + home       Die Turtle steht in der Mitte mit Ausrichtung nach oben.
//   + penUp      Der Stift wird von der Zeichenfläche genommen.
//   + penDown    Der Stift wird auf die Zeichenfläche gesetzt.
//   + penColor   Es wird eine Zeichenfarbe zugewiesen.
//   + clean      Der Zeichenbereich wird gelöscht.
//   - hide       Die Turtle wird unsichtbar.
//   - show       Die Turtle wird sichtbar
//
// Graphics-Context
// ================
// Die Turtle braucht einen Graphics-Context um zu Zeichnen. Dieser wird mit
// dem Container beim Konstruktor übergeben. Der Graphics-Context muss die
// folgende Schnittstelle erfüllen:
//   - drawLine(int startX, int startY, int stoppX, int stoppY)
//     Zeichnet eine Linie die bei startX/startY beginnt
//     und bei stoppX/stoppY endet.
//   - clearRect(int x, int y, int width, int height)
//     Löschen eines rechteckigen Zeichenbereichs.
//   - setColor(Color color)
//     Setzt eine Zeichenfarbe für die Zeichenbefehle wie drawLine.
//
// Author:  Martin Walser
// Date:    31.12.2008
// Version: 1.0

import java.awt.*;

public class Turtle{
  protected double    x,y;                // Position der Turtle.
  protected double    angle     = 180.0;  // Blickwinkel der Turtle.
  protected boolean   isPenDown = true;   // Gibt an ob gezeichnet wird.
  protected int       width;              // Breite des Zeichenbereiches.
  protected int       height;             // Höhe des Zeichenbereichs.
  protected Color     color;              // Zeichenfarbe der Turtle.
  protected Graphics  graphics;           // Graphics-Context.
  protected Container container;          // Behälter in dem gezeichnet wird.
  
  // Einfachster Konstruktor. Es wird ein einen Graphics-Context benötigt.
  // Turtle steht in der Mitte mit Blickrichtung anch oben.
  public Turtle(Container newContainer){
    this(newContainer, 0, 0, 0);
  }
  
  // Konstruktor mit Startposition und Startrichtung.
  public Turtle(Container newBox, double newX, double newY, double newAngle){
    // Übernahme der Konstuktor-Parameter.
    angle     = newAngle + 180;
    container = newBox;
    graphics  = container.getGraphics();
    
    // Übernahme der Grösse des Zeichenbereichs.
    width  = newBox.getBounds().width;
    height = newBox.getBounds().height;
    
    // Startposition ist auf Mitte bezogen.
    x = width /2 + newX;
    y = height/2 + newY;
  }
  
  // Bewegung der Turtle um eine mitgegebene Länge.
  // Basismethode für forward (+) und back (-).
  private void moveBy(double length){
    // Zeichenfarbe setzen.
    graphics.setColor(color);
    
    // Umrechnung von Grad in Radians.
    double radians = angle * Math.PI/180;

    // Berechnen der Endposition aus Startposition und Länge.
    double newX = x + length * Math.sin(radians);
    double newY = y + length * Math.cos(radians);

    // Zeichnen der Turtle-Spur.
    if(isPenDown) graphics.drawLine((int)x,(int)y,(int)newX,(int)newY);

    // Setzen der neuen Position der Turtle.
    x = newX;
    y = newY;
  }

  // Schnittstellen-Methoden
  // =======================
  // Für die parametrierten Methoden ist jeweils
  // eine int und ein double Version notwendig.

  // Vorwärtsbewegung der Turtle um eine mitgegebene Länge.
  public void forward  (double length){moveBy(length);}
  public void forward  (int    length){moveBy(length);}
  
  // Rückwärtsbewegung der Turtle um eine mitgegebene Länge.
  public void back     (double length){moveBy((-1)*length);}
  public void back     (int    length){moveBy((-1)*length);}
  
  // Drehung nach rechts um einen mitgegebenen Winkel.
  public void turnRight(double degree){angle -= degree;}
  public void turnRight(int    degree){angle -= degree;}
  
  // Drehung nach links um einen mitgegebenen Winkel.
  public void turnLeft (double degree){angle += degree;}
  public void turnLeft (int    degree){angle += degree;}
  
  // Stift hoch und runter.
  // Definiert, ob die Bewegung der Turtle eine Spur hinterlässt.
  public void penUp  (){isPenDown = false;}
  public void penDown(){isPenDown = true;}
  
  // Zeichenfarbe setzen.
  public void penColor(Color newColor){color = newColor;}
  
  // Löschen des Zeichnungsbereichs.
  public void clean  (){graphics.clearRect(0,0,width,height);}
  
  // Platzieren der Turtle auf dem Ausgangspunkt.
  public void home(){
    x     = width /2;
    y     = height/2;
    angle = 180.0;
  }
}

