Delphi 完成后如何使图像向下移动

Delphi 完成后如何使图像向下移动,delphi,delphi-xe2,Delphi,Delphi Xe2,目前我有一个TCard(TGraphic控件),我可以用一小步向上移动x。但是我不知道怎么把它移回去 我从 TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation); 在这里面 {这将导致攻击失败} procedure TGameData.AnimateAttack(slot: Integer;card: TCard); //add value as integer ,

目前我有一个TCard(TGraphic控件),我可以用一小步向上移动x。但是我不知道怎么把它移回去

我从

           TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation);
在这里面 {这将导致攻击失败}

procedure TGameData.AnimateAttack(slot: Integer;card: TCard);  //add value as integer ,
var
i : integer;
begin
i:=0;
   if slot = 1 then
        begin
           //TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation,nil);
           TCardMover.Slide(Card,point(Card.Left,Card.Top -10),CARD_SLIDE_TIME,Animation,TerminateCall);
        end;
   if slot = 2 then
        begin
          TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation,TerminateCall);  // DMc Just to test card movement
        end;
   if slot = 3  then
        begin
          TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation,TerminateCall);  // DMc Just to test card movement
        end;
end;
然后我把它叫做

procedure TGameData.attack;
begin
    animateAttack(1,fgame.Slot1);
end;
如果我像这样在animateattack中的tCardMover.slide后面运行

   TCardMover.Slide(card,point(card.Left,card.Top -10),CARD_SLIDE_TIME,Animation);
   TCardMover.Slide(card,point(card.Left,card.Top +10),CARD_SLIDE_TIME,Animation);
它试图做到这两个,我假设由于移动是一个单独的线程?我如何解决这个问题,以便我可以移出-10,然后在卡移动完成后移动+10-10

这是TCardMover

{ TCardMover }

function TCardMover.Arrived: boolean;
begin
  Result := (FPosNow.X = FPosDest.X) and (FPosNow.Y = FPosDest.Y);
end;

procedure TCardMover.CalculateNextStop;
var
  Elapsed : integer;
begin
  while FTickNext < GetTickCount do                 // When is next re-draw due?
    FTicknext := FTickNext + CARD_MOVE_INTERVAL;


  if FTickNext >= FTickEnd then   // Are we there yet Dad?
  begin                           // If the journey has taken long enough, move
    FTickNext := FTickEnd;        // to our destination without further delay,
    FPosNow   := FPosDest;        // then bail.
  end
  else
  begin
    // If we get here we are still en route so calculate where to re-draw.
    Elapsed := GetTickCount - FTickStart;                // How much time will journey have taken at next re-draw?
    FPosNow.X := FPosStart.X + round((Elapsed/FTickJourney)*FJourney.X);  // Where will card be at next re-draw?
    FPosNow.Y := FPosStart.Y + round((Elapsed/FTickJourney)*FJourney.Y);
  end;
end;

procedure TCardMover.Execute;
begin
  while not terminated and not Arrived do
  begin
    CalculateNextStop;
    WaitTillDue;
    Synchronize(NotifyHost);
  end;
end;

class procedure TCardMover.Slide(aCard: TCard; aDestination: TPoint; aJourneyTime: cardinal; DrawProc : TNotifyEvent);
begin
  with TCardMover.Create(START_IMMEDIATELY) do
  begin
    FTickStart      := GetTickCount;
    FTickNext       := FTickStart;
    FTickEnd        := FTickStart + aJourneyTime;
    FPosStart       := Point(aCard.Left,aCard.Top);
    FCard           := aCard;
    FPosDest        := aDestination;
    FTickJourney    := aJourneyTime;
    FreeOnTerminate := TRUE;
    FOnMove         := DrawProc;
    FJourney.X      := FPosDest.X - FPosStart.X;
    FJourney.Y      := FPosDest.Y - FPosStart.Y;
  end;
end;

procedure TCardMover.NotifyHost;
begin
  if assigned(FOnMove) then
    FOnMove(Self);
end;

procedure TCardMover.WaitTillDue;
var
  TicksNow : cardinal;
begin
  TicksNow := GetTickCount;
  if TicksNow < FTickNext then
    SleepEx(FTickNext-TicksNow,DO_NOT_QUIT_EARLY);
end;
{TCardMover}
函数TCardMover.arrized:boolean;
开始
结果:=(FPosNow.X=FPosDest.X)和(FPosNow.Y=FPosDest.Y);
终止
程序TCardMover.CalculateNextStop;
变量
时间:整数;
开始
当FTickNext=FTickEnd那么//我们到了吗,爸爸?
开始//如果旅程花费的时间足够长,请离开
FTickNext:=FTickEnd;//毫不拖延地赶到我们的目的地,
FPosNow:=FPosDest;//然后保释。
终止
其他的
开始
//如果我们到了这里,我们仍然在途中,所以请计算重新绘制的位置。
已用时间:=GetTickCount-FTickStart;//下一次重画时,旅程需要多少时间?
FPosNow.X:=FPosStart.X+round((经过的/FTickJourney)*FJourney.X);//下次重新抽牌时牌在哪里?
FPosNow.Y:=FPosStart.Y+round((经过的/FTickJourney)*FJourney.Y);
终止
终止
过程TCardMover.Execute;
开始
未终止且未到达时,请执行以下操作:
开始
计算下止点;
韦蒂尔杜;
同步(通知主机);
终止
终止
类过程TCardMover.Slide(aCard:TCard;aDestination:TPoint;aJourneyTime:cardinal;DrawProc:TNotifyEvent);
开始
使用TCardMover.Create(立即启动)do
开始
FTickStart:=GetTickCount;
FTickNext:=FTickStart;
FTickEnd:=FTickStart+aJourneyTime;
FPosStart:=点(aCard.Left,aCard.Top);
FCard:=aCard;
FPosDest:=指定值;
ftickTravely:=每小时一次;
FreeOnTerminate:=真;
FOnMove:=DrawProc;
FJourney.X:=FPosDest.X-FPosStart.X;
FJourney.Y:=FPosDest.Y-FPosStart.Y;
终止
终止
程序TCardMover.NotifyHost;
开始
如果已分配(FOnMove),则
丰莫夫(自我);
终止
程序TCardMover.waitilldue;
变量
蒂克斯诺:红衣主教;
开始
TicksNow:=GetTickCount;
如果单击“下一步”,则
SleepEx(FTickNext TicksNow,不要过早退出);
终止

一种方法是向类方法中添加一个常规参数,并提供一个OnTerminate事件。因此,将在第一个线程终止后调用第二个线程:

class procedure TCardMover.Slide(aCard: TShape; aDestination: TPoint; 
           aJourneyTime:cardinal ; DrawProc : TNotifyEvent; CallOnTerminate: TNotifyEvent);
begin
  with TCardMover.Create(false) do
  begin
    FTickStart      := GetTickCount;
    // .....
    OnTerminate := CallOnTerminate;
  end;
end;


procedure TAForm.TerminateCall(Sender: TObject);
begin
 TCardMover.Slide(Card ,point(Card.Left,Card.Top +100),50,Animation,nil);
end;

// Call the method and provide a procedure which will be called if the thread terminates
begin
 TCardMover.Slide(Card,point(Card.Left,Card.Top -100),50,Animation,TerminateCall);
end;

另一种方法是更改TCardMover类以处理动画列表。

首先,我将从一个对象开始,作为一个动画制作者,它可以触发多个动画

type
  IAnimation = interface
   {GUID}
   function IsFinished : Boolean;
   procedure Step;
 end;

 TAnimator = class
 private
   FAnimations : TList<IAnimation>;
   FTimer : TTimer;
   procedure TimerEvent( Sender : TObject );
 public
   constructor Create;
   destructor Destroy; override;
   procedure Add( AAnimation : IAnimation );
 end;

constructor TAnimator.Create;
begin
  inherited;
  FAnimations := TList<IAnimation>.Create;

  FTimer := TTimer.Create( nil );
  FTimer.Interval := 25; // whatever you like
  FTimer.OnTimer := TimerEvent;
  FTimer.Enabled := True;
end;

destructor Destroy;
begin
  FTimer.Free;
  FAnimations.Free;
  inherited;
end;

procedure TAnimator.Add( AAnimation : IAnimation );
begin
  FAnimations.Add( AAnimation );
end;

procedure TAnimator.TimerEvent( Sender : TObject );
var
  LIdx : Integer;
  LAnimation : IAnimation;
begin
  LIdx := 0;
  while LIdx < FAnimations.Count do
  begin
    LAnimation := FAnimations[LIdx];
    LAnimation.Step;
    if LAnimation.IsFinished then
      FAnimations.Remove( LAnimation )
    else
      Inc( LIdx );
  end;
end;

您的线程只有一个等待部分和一个同步移动部分。你可以在你的表格上用一个简单的TTimer来处理这个问题。我试过了,但有几个问题。。首先,我更新了我如何攻击。。我称攻击为提供一个插槽和TCard。然后我使用这些值运行AnimateAttack。因此,不确定如何设置TerminateCall过程。主要原因是我不确定如何将数据“插槽”和“卡”发送回此过程而不出错。由于您使用的是TNotifyEvents,因此您可以在事件中访问TCardMover(发送方)。您可以在类过程幻灯片中向线程提供所需的任何信息。这与您在DrawProc中访问PosNow相同。奇怪,在terminatecall中,我在卡和卡上遇到错误。左/右的一个不同之处是我有TGamedata。terminatecall中,与PosNow和DrawProc一样,我使用TCardmover.PosNow。发射型计算机断层扫描仪。。我将尝试将其添加到TCardMover
type
  TAnimationSequence = class( TInterfacedObject, IAnimation )
  private
    FAnimations : TQueue<IAnimation>;
    function IsFinished : Boolean;
    procedure Step;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add( AAnimation : IAnimation );
  end;

constructor TAnimationSequence.Create;
begin
  inherited;
  FAnimations := TQueue<IAnimation>.Create;
end;

destructor TAnimationSequence.Destroy;
begin
  FAnimations.Free;
  inherited;
end;

function TAnimationSequence.IsFinished : Boolean;
begin
  Result := FQueue.Count = 0;
end;

procedure Step;
var
  LAnimation : IAnimation;
begin
  LAnimation := FAnimations.Peek;
  LAnimation.Step;
  if LAnimation.IsFinished then
    LAnimation := FAnimations.Dequeue;
end;
var
  LSequence : TAnimationSequence;
begin
  LSequence := TAnimationSequence.Create;

  LSequence.Add( TControlMoveUpAnimation.Create( MyCard, 10 ) );
  LSequence.Add( TControlMoveDownAnimation.Create( MyCard, 10 ) );
  LSequence.Add( TControlMoveUpAnimation.Create( MyCard, 8 ) );
  LSequence.Add( TControlMoveDownAnimation.Create( MyCard, 8 ) );
  LSequence.Add( TControlMoveUpAnimation.Create( MyCard, 4 ) );
  LSequence.Add( TControlMoveDownAnimation.Create( MyCard, 4 ) );

  MyAnimator.Add( LSequence );
end;