Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

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

pcurtis

• Hero Member
• Posts: 841
[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;
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
Laz 2.0.12
FPC 3.2.0

Lulu

• Full Member
• Posts: 143
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.
Have a nice life

pcurtis

• Hero Member
• Posts: 841
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
Laz 2.0.12
FPC 3.2.0

Handoko

• Hero Member
• Posts: 4430
• 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
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: 4430
• 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
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: 841
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
Laz 2.0.12
FPC 3.2.0