Recent

Author Topic: [CLOSED] Help improving code  (Read 4171 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 951
[CLOSED] Help improving code
« on: December 07, 2021, 08:25:36 pm »
I would like a little help with this code.
Basically it animates moving and zooming a control, but its not too smooth. Any ideas?

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Zoom(aSource : TControl;
  2.                       aDestination : TControl;
  3.                       aSteps : Integer);
  4. var
  5.   iTemp : Integer;
  6.   dX, dY, dWidth, dHeight : Integer;
  7. begin
  8.   SourceCenter.X := aSource.BoundsRect.Location.X + aSource.Width div 2;
  9.   SourceCenter.Y := aSource.BoundsRect.Location.Y + aSource.Height div 2;
  10.   DestinationCenter.X := aDestination.Width div 2;
  11.   DestinationCenter.Y := aDestination.Height div 2;
  12.  
  13.   dX := (DestinationCenter.X - SourceCenter.X) div aSteps;
  14.   dY := (DestinationCenter.Y - SourceCenter.Y) div aSteps;
  15.  
  16.   while aSteps > 0 do
  17.     begin
  18.       SourceCenter.X := SourceCenter.X + dX;
  19.       SourceCenter.Y := SourceCenter.Y + dY;
  20.       aa.Inflate(14,14);
  21.       aa.SetLocation(SourceCenter.X - (aSource.Width div 2), SourceCenter.Y - (aSource.Height div 2));
  22.       aSource.BoundsRect := aa;
  23.       aSteps := aSteps - 1;
  24.       Application.ProcessMessages;
  25.     end;
  26. end;
  27.  
  28.  

Use is simple. Drop a button on a form and call

Code: Pascal  [Select][+][-]
  1. Zoom(Button1, Form1, 10);
  2.  
« Last Edit: December 08, 2021, 08:39:59 am by pcurtis »
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Lulu

  • Full Member
  • ***
  • Posts: 226
Re: Help improving code
« Reply #1 on: December 07, 2021, 08:42:08 pm »
Hi pcurtis,
may be by increasing the step count ? in your example, 10 steps is low if the 2 control are far away.
wishing you a nice life

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Help improving code
« Reply #2 on: December 07, 2021, 08:52:08 pm »
10 is ok. Anyway Ive got a small display.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Help improving code
« Reply #3 on: December 08, 2021, 07:49:23 am »
I tested your code, it seemed okay to me. What did you mean not too smooth? Maybe you need to put a Sleep command in the loop.

I saw you used global variables. For this simple case, you don't need to use any global variables. I am not very sure what exactly you want to do, but here this is my version:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Image1: TImage;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.     procedure ZoomTo(TheOBject, Target: TControl; Steps: Integer);
  20.   end;
  21.  
  22. var
  23.   Form1: TForm1;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.Button1Click(Sender: TObject);
  32. begin
  33.   ZoomTo(Button1, Image1, 10);
  34. end;
  35.  
  36. procedure TForm1.ZoomTo(TheOBject, Target: TControl; Steps: Integer);
  37. var
  38.   iX, iY, iW, iH: Integer;
  39.   i: Integer;
  40. begin
  41.   // Bad parameters
  42.   if not(Assigned(TheOBject)) then Exit;
  43.   if not(Assigned(Target)) then Exit;
  44.   if Steps < 1 then Exit;
  45.   // Position and size increment
  46.   iX := (Target.Left   - TheOBject.Left)   div Steps;
  47.   iY := (Target.Top    - TheOBject.Top)    div Steps;
  48.   iW := (Target.Width  - TheOBject.Width)  div Steps;
  49.   iH := (Target.Height - TheOBject.Height) div Steps;
  50.   // Animate
  51.   for i := 1 to Steps - 1 do
  52.   begin
  53.     TheOBject.Left   := TheOBject.Left   + iX;
  54.     TheOBject.Top    := TheOBject.Top    + iY;
  55.     TheOBject.Width  := TheOBject.Width  + iW;
  56.     TheOBject.Height := TheOBject.Height + iH;
  57.     Application.ProcessMessages;
  58.     Sleep(30);
  59.   end;
  60.   // Precise position and size
  61.   TheOBject.SetBounds(Target.Left, Target.Top, Target.Width, Target.Height);
  62. end;
  63.  
  64. end.

Playing with animation is fun. If you want to see more GUI animation, here:
https://forum.lazarus.freepascal.org/index.php/topic,37943.msg256549.html#msg256549


Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Help improving code
« Reply #4 on: December 08, 2021, 08:16:31 am »
Sorry, my previous code has calculation issue. If you set Steps = 30 or more then you will see what I mean.

Here is the better version:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Image1: TImage;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.     procedure ZoomTo(TheOBject, Target: TControl; Steps: Integer);
  20.   end;
  21.  
  22. var
  23.   Form1: TForm1;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.Button1Click(Sender: TObject);
  32. begin
  33.   ZoomTo(Button1, Image1, 40);
  34. end;
  35.  
  36. procedure TForm1.ZoomTo(TheOBject, Target: TControl; Steps: Integer);
  37. const
  38.   oX: Integer = 0;
  39.   oY: Integer = 0;
  40.   oW: Integer = 0;
  41.   oH: Integer = 0;
  42. var
  43.   dX, dY, dW, dH: Integer;
  44.   i: Integer;
  45. begin
  46.   // Bad parameters
  47.   if not(Assigned(TheOBject)) then Exit;
  48.   if not(Assigned(Target)) then Exit;
  49.   if Steps < 1 then Exit;
  50.   // Store orginal poisition and size
  51.   oX := TheOBject.Left;
  52.   oY := TheOBject.Top;
  53.   oW := TheOBject.Width;
  54.   oH := TheOBject.Height;
  55.   // Position and size difference
  56.   dX := Target.Left   - TheOBject.Left;
  57.   dY := Target.Top    - TheOBject.Top;
  58.   dW := Target.Width  - TheOBject.Width;
  59.   dH := Target.Height - TheOBject.Height;
  60.   // Animate
  61.   for i := 1 to Steps -1 do
  62.   begin
  63.     TheOBject.Left   := oX + Round(i * dx / Steps);
  64.     TheOBject.Top    := oY + Round(i * dY / Steps);
  65.     TheOBject.Width  := oW + Round(i * dW / Steps);
  66.     TheOBject.Height := oH + Round(i * dH / Steps);
  67.     Application.ProcessMessages;
  68.     Sleep(30);
  69.   end;
  70.   // Precise position and size
  71.   TheOBject.SetBounds(Target.Left, Target.Top, Target.Width, Target.Height);
  72. end;
  73.  
  74. end.



Basically it animates moving and zooming a control, but its not too smooth. Any ideas?

Maybe, precision issue. You used integer division, which may decrease the precision. Possible solutions: use real variables or do the calculation inside the loop like what I did in the code above.
« Last Edit: December 08, 2021, 08:22:29 am by Handoko »

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Help improving code
« Reply #5 on: December 08, 2021, 08:39:15 am »
Thanks for your help. It's all I needed.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

 

TinyPortal © 2005-2018