{
  turtle.pas
  version 0.2 2012-08-31

  changelog:
    2012-08-31:
      bug in updateAngle bereinigt
      (vorzeichenfehler AktuellAngle:=2*turtlePI+{hier stand -}AktuellAngle;
}

unit turtle;

interface

uses
  Classes, Graphics;

const
  turtlePI: Extended = 3.14159265358979323846264338327950288419716939937510582;

type
  { TExtendedPoint }
  TExtendedPoint = record
    X, Y: Extended;
  end;

  { TTurtle }
  TTurtle = class
  private
    AktuellPoint: TExtendedPoint;
    AktuellAngle: Extended;
    Surface: TCanvas;
    procedure updateAngle;
  public
    {constructor}
    constructor Create(myCanvas: TCanvas); Overload;
    constructor Create(myCanvas: TCanvas; dest: TExtendedPoint); Overload;
    constructor Create(myCanvas: TCanvas; dest: TPoint); Overload;
    constructor Create(myCanvas: TCanvas; destX, destY: Extended); Overload;
    constructor Create(myCanvas: TCanvas; destX, destY: LongInt); Overload;
    {destructor}
    destructor Destroy;
    {turtle functions}
    procedure MoveTo(dest: TExtendedPoint); Overload;
    procedure MoveTo(dest: TPoint); Overload;
    procedure MoveTo(destX, destY: Extended); Overload;
    procedure MoveTo(destX, destY: LongInt); Overload;
    procedure SetDirection(angle: Extended);
    procedure TurnRight(angle: Extended);
    procedure TurnLeft(angle: Extended);
    procedure DrawLine(length: Extended);
    procedure MoveForward(length: Extended);
    {getter functions}
    function GetAktuellPoint: TExtendedPoint;
    function GetAktuellXPos: Extended;
    function GetAktuellYPos: Extended;
    function GetAktuellAngle: Extended;
    function GetSurface: TCanvas;
    {setter functions}
    procedure SetAktuellPoint(point: TExtendedPoint); Overload;
    procedure SetAktuellPoint(point: TPoint); Overload;
    procedure SetAktuellPoint(x, y: Extended); Overload;
    procedure SetAktuellPoint(x, y: LongInt); Overload;
    procedure SetAktuellXPos(x: Extended); Overload;
    procedure SetAktuellXPos(x: LongInt); Overload;
    procedure SetAktuellYPos(y: Extended); Overload;
    procedure SetAktuellYPos(y: LongInt); Overload;
    procedure SetSurface(myCanvas: TCanvas);
  end;

implementation

{ TTurtle }
procedure TTurtle.updateAngle;
begin
  while AktuellAngle < (-2*turtlePI) do
  begin
    AktuellAngle:=AktuellAngle+2*turtlePI;
  end;

  while AktuellAngle > (2*turtlePI) do
  begin
    AktuellAngle:=AktuellAngle-2*turtlePI;
  end;

  if AktuellAngle < 0 then
  begin
    AktuellAngle:=2*turtlePI+AktuellAngle;
  end;
end;

constructor TTurtle.Create(myCanvas: TCanvas);
begin
  Surface:=myCanvas;
  AktuellPoint.X:=Surface.Width/2;
  AktuellPoint.Y:=Surface.Height/2;
  AktuellAngle:=0;
  MoveTo(AktuellPoint);
end;

constructor TTurtle.Create(myCanvas: TCanvas; dest: TExtendedPoint);
begin
  Surface:=myCanvas;
  AktuellPoint:=dest;
  MoveTo(AktuellPoint);
end;

constructor TTurtle.Create(myCanvas: TCanvas; dest: TPoint);
begin
  Surface:=myCanvas;
  AktuellPoint.X:=dest.X;
  AktuellPoint.Y:=dest.Y;
  MoveTo(AktuellPoint);
end;

constructor TTurtle.Create(myCanvas: TCanvas; destX, destY: Extended);
begin
  Surface:=myCanvas;
  AktuellPoint.X:=destX;
  AktuellPoint.Y:=destY;
  MoveTo(AktuellPoint);
end;

constructor TTurtle.Create(myCanvas: TCanvas; destX, destY: LongInt);
begin
  Surface:=myCanvas;
  AktuellPoint.X:=destX;
  AktuellPoint.Y:=destY;
  MoveTo(AktuellPoint);
end;

destructor TTurtle.Destroy;
begin
  Surface.Free;
end;

procedure TTurtle.MoveTo(dest: TExtendedPoint);
begin
  SetAktuellPoint(dest);
  Surface.MoveTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

procedure TTurtle.MoveTo(dest: TPoint);
begin
  SetAktuellPoint(dest);
  Surface.MoveTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

procedure TTurtle.MoveTo(destX, destY: Extended);
begin
  SetAktuellPoint(destX, destY);
  Surface.MoveTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

procedure TTurtle.MoveTo(destX, destY: LongInt);
begin
  SetAktuellPoint(destX, destY);
  Surface.MoveTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

procedure TTurtle.SetDirection(angle: Extended);
begin
  AktuellAngle:=angle;
  updateAngle;
end;

procedure TTurtle.TurnRight(angle: Extended);
begin
  AktuellAngle:=AktuellAngle-angle;
  updateAngle;
end;

procedure TTurtle.TurnLeft(angle: Extended);
begin
  AktuellAngle:=AktuellAngle+angle;
  updateAngle;
end;

procedure TTurtle.DrawLine(length: Extended);
begin
  AktuellPoint.X:=AktuellPoint.X+length*cos(AktuellAngle);
  AktuellPoint.Y:=AktuellPoint.Y+length*sin(AktuellAngle);
  Surface.LineTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

procedure TTurtle.MoveForward(length: Extended);
begin
  AktuellPoint.X:=AktuellPoint.X+length*cos(AktuellAngle);
  AktuellPoint.Y:=AktuellPoint.Y+length*sin(AktuellAngle);
  Surface.MoveTo(Round(AktuellPoint.X), Surface.Height-Round(AktuellPoint.Y));
end;

function TTurtle.GetAktuellPoint: TExtendedPoint;
begin
  result:=AktuellPoint;
end;

function TTurtle.GetAktuellXPos: Extended;
begin
  result:=AktuellPoint.X;
end;

function TTurtle.GetAktuellYPos: Extended;
begin
  result:=AktuellPoint.Y;
end;

function TTurtle.GetAktuellAngle: Extended;
begin
  result:=AktuellAngle;
end;

function TTurtle.GetSurface: TCanvas;
begin
  result:=Surface;
end;

procedure TTurtle.SetAktuellPoint(point: TExtendedPoint);
begin
  AktuellPoint:=point;
end;

procedure TTurtle.SetAktuellPoint(point: TPoint);
begin
  AktuellPoint.X:=point.X;
  AktuellPoint.Y:=point.Y;
end;

procedure TTurtle.SetAktuellPoint(x, y: Extended);
begin
  AktuellPoint.X:=x;
  AktuellPoint.Y:=y;
end;

procedure TTurtle.SetAktuellPoint(x, y: LongInt);
begin
  AktuellPoint.X:=x;
  AktuellPoint.Y:=y;
end;

procedure TTurtle.SetAktuellXPos(x: Extended);
begin
  AktuellPoint.X:=x;
end;

procedure TTurtle.SetAktuellXPos(x: LongInt);
begin
  AktuellPoint.X:=x;
end;

procedure TTurtle.SetAktuellYPos(y: Extended);
begin
  AktuellPoint.Y:=y;
end;

procedure TTurtle.SetAktuellYPos(y: LongInt);
begin
  AktuellPoint.Y:=y;
end;

procedure TTurtle.SetSurface(myCanvas: TCanvas);
begin
  Surface:=myCanvas;
end;

end.

