pascalabcnet/bin/Lib/TurtleWPF.pas

272 lines
8 KiB
ObjectPascal
Raw Permalink Normal View History

unit TurtleWPF;
interface
uses GraphWPF;
/// Передвигает Черепаху вперёд на расстояние r
procedure Forw(r: real);
/// Передвигает Черепаху назад на расстояние r
procedure Back(r: real);
/// Поворачивает Черепаху на угол da по часовой стрелке
procedure Turn(da: real);
/// Поворачивает Черепаху на угол da влево
procedure TurnLeft(da: real);
/// Поворачивает Черепаху на угол da вправо
procedure TurnRight(da: real);
/// Возвращает случайный цвет
function RandomColor: Color;
/// Возвращает цвет по красной, зеленой и синей составляющей (в диапазоне 0..255)
function RGB(r,g,b: byte): Color;
/// Устанавливает скорость черепашки (от 1 до 10)
procedure SetSpeed(sp: integer);
/// Прячет Черепаху
procedure Hide;
/// Показывает Черепаху
procedure Show;
/// Опускает перо Черепахи
procedure Down;
/// Поднимает перо Черепахи
procedure Up;
/// Устанавливает ширину линии
procedure SetWidth(w: real);
/// Устанавливает цвет линии
procedure SetColor(c: GColor);
/// Перемещает Черепаху в точку (x,y)
procedure MoveTo(x,y: real);
/// Сохраняет изображение, нарисованное Черепахой, в файл fname (например, 'a.png')
procedure Save(fname: string);
type Colors = GraphWPF.Colors;
{type turtle = static class
/// Передвигает Черепаху вперёд на расстояние r
static procedure Forw(r: real) := TurtleWPF.Forw(r);
/// Поворачивает Черепаху на угол da по часовой стрелке
static procedure Turn(da: real) := TurtleWPF.Turn(da);
/// Возвращает случайный цвет
static function RandomColor: Color := TurtleWPF.RandomColor;
/// Возвращает цвет по красной, зеленой и синей составляющей (в диапазоне 0..255)
static function RGB(r,g,b: byte): Color := TurtleWPF.RGB(r,g,b);
/// Устанавливает скорость черепашки (от 1 до 10)
static procedure SetSpeed(sp: integer) := TurtleWPF.SetSpeed(sp);
/// Прячет Черепаху
static procedure Hide := TurtleWPF.Hide;
/// Показывает Черепаху
static procedure Show := TurtleWPF.Show;
/// Опускает перо Черепахи
static procedure Down := TurtleWPF.Down;
/// Поднимает перо Черепахи
static procedure Up := TurtleWPF.Up;
/// Устанавливает ширину линии
static procedure SetWidth(w: real) := TurtleWPF.SetWidth(w);
/// Устанавливает цвет линии
static procedure SetColor(c: GColor) := TurtleWPF.SetColor(c);
/// Перемещает Черепаху в точку (x,y)
static procedure MoveTo(x,y: real) := TurtleWPF.MoveTo(x,y);
/// Сохраняет изображение, нарисованное Черепахой, в файл fname (например, 'a.png')
static procedure Save(fname: string) := TurtleWPF.Save(fname);
end;}
implementation
{$resource 'turtle.png'}
uses WPFObjects,GraphWPFBase;
uses System.Windows.Media.Animation;
uses System.Windows.Media;
uses System.Windows.Media.Imaging;
var
TurtleX: real := 400;
TurtleY: real := 300;
w := 24; // размер изображения Черепахи
type
TurtleHelper = class(PictureWPF)
private
function CreateBitmapImageFromResource(resourcename: string): BitmapImage;
begin
var bi := new BitmapImage();
bi.BeginInit();
bi.StreamSource := GetResourceStream(resourcename);
bi.EndInit();
Result := bi;
end;
procedure InitObFromResource(x,y,w,h: real; fname: string);
begin
var b := CreateBitmapImageFromResource(fname);
Rest(x,y,w,h,b);
end;
procedure AnimMoveByPE(a,b,sec: real);
begin
var v := CreateVisual;
var p := Center;
var (x,y) := (transl.X,transl.Y);
var ax := new DoubleAnimation(a + x, System.TimeSpan.FromSeconds(sec));
var ay := new DoubleAnimation(b + y, System.TimeSpan.FromSeconds(sec));
ax.FillBehavior := FillBehavior.Stop;
ay.FillBehavior := FillBehavior.Stop;
var transl1 := transl;
ax.Completed += (o,e) -> begin
DrawOnVisual(v,dc->dc.DrawLine(GraphWPF.Pen.PenConstruct,p,Pnt(p.X + a,p.Y + b)));
transl1.X := x + a; // transl - ошибка с лямбдами!
end;
ay.Completed += (o,e) -> begin
transl1.Y := y + b;
end;
ax.CurrentTimeInvalidated += (o,e) ->
DrawOnVisual(v,dc->dc.DrawLine(GraphWPF.Pen.PenConstruct,p,Pnt(Center.X,Center.Y)));
transl.BeginAnimation(TranslateTransform.XProperty, ax, HandoffBehavior.Compose);
transl.BeginAnimation(TranslateTransform.YProperty, ay, HandoffBehavior.Compose);
end;
public
constructor (x,y,w,h: real; fname: string) := Invoke(InitObFromResource,x,y,w,h,fname);
procedure AnimMoveByE(a,b,sec: real);
begin
Invoke(AnimMoveByPE,a,b,sec);
Sleep(Round(sec*1000 + 50)); // 50 мс - За это время анимация должна закончиться
end;
procedure AnimRotateE(a,sec: real);
begin
AnimRotate(a,sec);
Sleep(Round(sec*1000 + 50));
end;
end;
var t: TurtleHelper;
var
a: real := 0;
dr := False;
speed := 10;
Window := GraphWPF.Window;
function RandomColor := GraphWPF.RandomColor;
function RGB(r,g,b: byte) := GraphWPF.RGB(r, g, b);
var sl := 30;
procedure SetSpeed(sp: integer);
begin
speed := sp.Clamp(1,10);
if sp > 10 then
sl := 0
else sl := 30;
end;
procedure Hide;
begin
t.Visible := False;
end;
procedure Show;
begin
t.Visible := True;
end;
/// Поворачивает Черепаху на угол da по часовой стрелке
procedure Turn(da: real);
begin
a += da;
if speed = 10 then
begin
t.Rotate(da);
Sleep(sl);
end
else
begin
if dr then
t.AnimRotateE(da,Abs(da/(60*speed)))
else
begin
t.AnimRotate(da,Abs(da/(60*speed)));
Sleep(Round(Abs(da/(60*speed))*1000)+50);
end;
end;
end;
procedure TurnLeft(da: real) := Turn(-da);
procedure TurnRight(da: real) := Turn(da);
/// Продвигает Черепаху вперёд на расстояние r
procedure Forw(r: real);
begin
var v := r * Vect(Cos(DegToRad(a)),Sin(DegToRad(a)));
var (a,b) := (v.X,v.Y);
TurtleX += a;
TurtleY += b;
if (speed = 10) or (r < 20) then
begin
if dr then
GraphWPF.LineTo(TurtleX,TurtleY)
else GraphWPF.MoveTo(TurtleX,TurtleY);
t.MoveBy(a,b);
Sleep(sl);
end
else
begin
if dr then
begin
t.AnimMoveByE(a,b,r/(50*speed)); // 450 в секунду при скорости 9
GraphWPF.MoveTo(TurtleX,TurtleY);
end
else
begin
t.AnimMoveBy(a,b,r/(50*speed));
Sleep(Round(r/(50*speed)*1000)+50);
GraphWPF.MoveTo(TurtleX,TurtleY);
end;
end;
end;
procedure Back(r: real) := Forw(-r);
/// Опускает хвост Черепахи
procedure Down := dr := True;
/// Поднимает хвост Черепахи
procedure Up := dr := False;
/// Устанавливает ширину линии
procedure SetWidth(w: real) := GraphWPF.Pen.Width := w;
/// Устанавливает цвет линии
procedure SetColor(c: GColor) := GraphWPF.Pen.Color := c;
/// Перемещает Черепаху в точку (x,y)
procedure MoveTo(x,y: real);
begin
TurtleX := x;
TurtleY := y;
GraphWPF.MoveTo(x,y);
t.Center := Pnt(x,y);
end;
procedure Save(fname: string) := Window.Save(fname);
begin
Window.Title := 'Исполнитель Черепаха WPF';
t := new TurtleHelper(TurtleX-w/2,TurtleY-w/2,w,w,'turtle.png');
//Pen.RoundCap := True;
MoveTo(TurtleX,TurtleY);
a -= 90;
end.