【问题标题】:Delphi, How to make a shape stop movingDelphi,如何使形状停止移动
【发布时间】:2013-04-21 17:31:27
【问题描述】:

我正在尝试使用 2 个形状和 2 个计时器使一个形状向另一个方向移动,但我真的看不到。我在想:

在开始的时候,我会让shape 1计算shape 2的距离然后朝它移动,这就是我所做的,我还添加了cmets来帮助你理解代码,因为它有点混乱:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
timer1.Interval:=100;           //set interval=200
                            //begin
if shape1.Left=shape2.Left then
begin
shape1.Left:=shape1.left         //If shape's 1 coordinates = shape's 2 then
end else                        //shape1.left:=stop moving else do
begin                           //find if shape 2 is right or left from shape 1
if shape1.left>shape2.Left then
begin
shape1.Left:=shape1.Left-5;
end else shape1.Left:=shape1.Left+5;
//Moving to shape2.left until shape1.left:=shape2.left



end;
end;


procedure TForm1.Timer2Timer(Sender: TObject);
begin
timer2.Interval:=100;      //the same method as timer1

if shape1.top=shape2.top then
begin
shape1.top:=shape1.top
end else
begin
if shape1.top>shape2.top then
begin
shape1.top:=shape1.top-5;
end else shape1.top:=shape1.top+5;

end;
end;

end.

shape1 现在做的是向形状 2 移动,但它并没有停止移动,我的意思是它粘在形状 2 上,但它仍在倒置移动,但不是从形状 2 左右移动。我检查了定时器2的代码,没有错。

【问题讨论】:

  • 您似乎要求我们完成您程序中的每一个小步骤。如果你今晚睡得好,也许你明天可以自己解决问题?
  • 无论如何:(1) 只使用一个计时器。 (2) shape1.Left:=shape1.left 是微不足道的空操作。 (3) 在设计时设置定时器的间隔,或一次。不是每秒10次! (4) shape1.top:=shape1.top 也是空操作。 (5) 用Delphi做动画一点都不难,只要你在实现之前考虑一下逻辑。
  • 问题是我不能:P。查看定时器2的程序,和定时器1一样,IF SHAPE1.TOP:=SHAPE2.TOP THEN SHAPE1.TOP:=SHAPE1.TOP ...就像说:嘿Shape1,如果你在shape2上移动,停止移动,但它没有
  • 因为SHAPE1.TOPSHAPE1.TOP 是同一个数字(不开玩笑!),SHAPE1.TOP:=SHAPE1.TOP 行完全没有任何作用。曾经。因此,如果顶部不相等,IF SHAPE1.TOP=SHAPE2.TOP THEN SHAPE1.TOP:=SHAPE1.TOP 什么也不做,如果它们相等,它仍然什么也不做。因此,代码在任何情况下都不做任何事情!
  • 如果你想停止动画,你可以...禁用计时器?

标签: delphi move shape


【解决方案1】:

试试下面的代码(赋值OnCreateOnPaint的形式,并将定时器设置为30毫秒的间隔):

unit Unit5;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TVector = record
    X, Y: real;
  end;

  TForm5 = class(TForm)
    Timer1: TTimer;
    procedure FormPaint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    FPosA, FPosB: TVector;
    v: TVector;
  public
    { Public declarations }
  end;

var
  Form5: TForm5;

implementation

uses Math;

{$R *.dfm}

const RADIUS = 16;

function RealPoint(X, Y: real): TVector;
begin
  result.X := X;
  result.Y := Y;
end;

function RoundPoint(P: TVector): TPoint;
begin
  result.X := round(P.X);
  result.Y := round(P.Y);
end;

procedure TForm5.FormCreate(Sender: TObject);
var
  DX, DY: real;
begin
  FPosA := RealPoint(32, 32);
  FPosB := RealPoint(500, 200);

  DX := FPosB.X - FPosA.X;
  DY := FPosB.Y - FPosA.Y;

  v.X := DX / 100;
  v.Y := DY / 100;
end;

function EllipseRectFromPoint(P: TVector): TRect;
var
  ScreenPoint: TPoint;
begin
  ScreenPoint := RoundPoint(P);
  result.Left := ScreenPoint.X - RADIUS;
  result.Right := ScreenPoint.X + RADIUS;
  result.Top := ScreenPoint.Y - RADIUS;
  result.Bottom := ScreenPoint.Y + RADIUS;
end;

procedure TForm5.FormPaint(Sender: TObject);
begin

  // Draw ball A
  Canvas.Brush.Color := clSkyBlue;
  Canvas.Ellipse(EllipseRectFromPoint(FPosA));

  // Draw ball B
  Canvas.Brush.Color := clMoneyGreen;
  Canvas.Ellipse(EllipseRectFromPoint(FPosB));

end;

procedure TForm5.Timer1Timer(Sender: TObject);
begin
  FPosA.X := FPosA.X + V.X;
  FPosA.Y := FPosA.Y + V.Y;
  Invalidate;

  if Hypot(FPosA.X - FPosB.X, FPosA.Y - FPosB.Y) < 0.1 then
  begin
    Timer1.Enabled := false;
    ShowMessage('We''re there!');
  end;
end;

end.

两个球:

unit Unit5;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TVector = record
    X, Y: real;
  end;

  TForm5 = class(TForm)
    Timer1: TTimer;
    procedure FormPaint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    AreWeThereYetA, AreWeThereYetB: boolean;
    FPosA, FPosB, FPosC: TVector;
    vA, vB: TVector;
  public
    { Public declarations }
  end;

var
  Form5: TForm5;

implementation

uses Math;

{$R *.dfm}

const RADIUS = 16;

function RealPoint(X, Y: real): TVector;
begin
  result.X := X;
  result.Y := Y;
end;

function RoundPoint(P: TVector): TPoint;
begin
  result.X := round(P.X);
  result.Y := round(P.Y);
end;

procedure TForm5.FormCreate(Sender: TObject);
var
  DX, DY: real;
begin
  FPosA := RealPoint(32, 32);
  FPosB := RealPoint(132, 32);
  FPosC := RealPoint(500, 200);

  DX := FPosC.X - FPosA.X;
  DY := FPosC.Y - FPosA.Y;
  vA.X := DX / 100;
  vA.Y := DY / 100;

  DX := FPosC.X - FPosB.X;
  DY := FPosC.Y - FPosB.Y;
  vB.X := DX / 200;
  vB.Y := DY / 200;

end;

function EllipseRectFromPoint(P: TVector): TRect;
var
  ScreenPoint: TPoint;
begin
  ScreenPoint := RoundPoint(P);
  result.Left := ScreenPoint.X - RADIUS;
  result.Right := ScreenPoint.X + RADIUS;
  result.Top := ScreenPoint.Y - RADIUS;
  result.Bottom := ScreenPoint.Y + RADIUS;
end;

procedure TForm5.FormPaint(Sender: TObject);
begin

  // Draw ball A
  Canvas.Brush.Color := clSkyBlue;
  Canvas.Ellipse(EllipseRectFromPoint(FPosA));

  // Draw ball B
  Canvas.Brush.Color := clMoneyGreen;
  Canvas.Ellipse(EllipseRectFromPoint(FPosB));

  // Draw ball C
  Canvas.Brush.Color := clRed;
  Canvas.Ellipse(EllipseRectFromPoint(FPosC));

end;

procedure TForm5.Timer1Timer(Sender: TObject);
begin

  if not AreWeThereYetA then
  begin
    FPosA.X := FPosA.X + VA.X;
    FPosA.Y := FPosA.Y + VA.Y;
  end;

  if not AreWeThereYetB then
  begin
    FPosB.X := FPosB.X + VB.X;
    FPosB.Y := FPosB.Y + VB.Y;
  end;

  Invalidate;

  if Hypot(FPosA.X - FPosC.X, FPosA.Y - FPosC.Y) < 0.1 then
    AreWeThereYetA := true;

  if Hypot(FPosB.X - FPosC.X, FPosB.Y - FPosC.Y) < 0.1 then
    AreWeThereYetB := true;

  if AreWeThereYetA and AreWeThereYetB then
  begin
    Timer1.Enabled := false;
    ShowMessage('We are there!');
  end;
end;

end.

使用数组和记录,很容易泛化为具有自定义属性(颜色、半径等)的N 球,甚至是随机属性。实现弹跳也很容易。此外,这里最好使用真正的向量类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 2020-05-13
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多