Lazarus

Free Pascal => Beginners => Topic started by: bradyhartsfield on January 11, 2018, 02:50:45 pm

Title: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 02:50:45 pm
hey,
 
i am back with my well known problem! so this is how far i am right now: i created my own processes to make it more structured. one is called "switch" and one is called "pythagoras". in the "switch" process i want the two circles to exchange velocities so it looks like they are bouncing off of each other.

i created a double loop for so that no circle is left out, but it isnt working.. my program is starting without any errors but the circle wont bounce off of eachother.

Code: Pascal  [Select][+][-]
  1. procedure pythagoras;
  2.   var d : real;
  3.   var j,i,c,a,b : integer;
  4. begin
  5.   for j := 1 to 20 do
  6.     for i := 2 to 20 do begin
  7.     d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  8.     if d <= r[j]+r[i]+12 then begin
  9.     switch
  10.     switch
  11.   end;
  12.  end;
  13. end;
  sooo, this is currently my "pythagoras" process. after "switch" i need to add something i will come back to that later. soo that code i wrote up there i got from my teacher, but i already modified it, for example i added the "switch" process and changed the letters "j" and "i".
my questions now:
do i need to define vx, vy, mx, my and r new like this :
Code: Pascal  [Select][+][-]
  1.   for i :=  1 to 20 do begin
  2.     r[j] := 20;
  3.     mx[j] := random(image1.width);
  4.     my[j] := random(image1.height);
  5.     vx[j] := random(10);
  6.     vy[j] := random(10);
  7.   end;  
and the same with i?
why is there at the part with the two "r`s" summed up a "+12" at the end?
btw: after the two "switch" i want to add (vx[j], vx) and (vy[j], vx) but when i do that there comes the error
Quote
Illegal qualifier
and the j and the i is marked.

this is my switch process:
Code: Pascal  [Select][+][-]
  1. procedure switch (Var a,b:integer);
  2. var zwischenspeicher : integer;
  3.   begin
  4.     zwischenspeicher := a;
  5.     a := b;
  6.     b := zwischenspeicher;
  7.   end;  

questions:
do i need two of those? so switch1 and switch2?


summed up:
I need to create 20 ellipses, spawning randomly, bouncing off the wall and moving around [DONE]
I need the ellipses to bounce off of each other when they touch [not done]

this is my whole code atm:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     Button2: TButton;
  18.     Image1: TImage;
  19.     Timer1: TTimer;
  20.     Timer2: TTimer;
  21.     procedure Button1Click(Sender: TObject);
  22.     procedure Button2Click(Sender: TObject);
  23.     procedure FormCreate(Sender: TObject);
  24.     procedure FormShowHint(Sender: TObject; HintInfo: PHintInfo);
  25.     procedure Image1Click(Sender: TObject);
  26.     procedure Timer1Timer(Sender: TObject);
  27.   private
  28.  
  29.   public
  30.  
  31.   end;
  32.  
  33. var
  34.   Form1: TForm1;
  35.   mx : array[1..20] of integer;
  36.   my : array[1..20] of integer;
  37.   vx : array[1..20] of integer;
  38.   vy : array[1..20] of integer;
  39.   r  : array[1..20] of integer;
  40.   zwischenspeicher1, zwischenspeicher2, c, c2,j,i,d : integer;
  41.  
  42.  
  43. implementation
  44.  
  45. {$R *.lfm}
  46.  
  47. { TForm1 }
  48.  
  49. procedure TForm1.Button1Click(Sender: TObject);
  50. begin
  51.   timer1.enabled := true;
  52. end;
  53.  
  54. procedure TForm1.Button2Click(Sender: TObject);
  55. begin
  56.   timer1.enabled := false;
  57. end;
  58.  
  59. procedure switch (Var a,b:integer);
  60. var zwischenspeicher : integer;
  61.   begin
  62.     zwischenspeicher := a;
  63.     a := b;
  64.     b := zwischenspeicher;
  65.   end;
  66.  
  67.  
  68. procedure pythagoras;
  69.   var d : real;
  70.   var j,i,vx,vy,c,a,b : integer;
  71. begin
  72.   for j := 1 to 20 do
  73.     for i := 2 to 20 do begin
  74.     d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  75.     if d <= r[j]+r[i]+12 then begin
  76.     switch
  77.     switch
  78.   end;
  79.  end;
  80. end;
  81.  
  82. procedure TForm1.FormCreate(Sender: TObject);
  83. begin
  84.   form1.color:=clpurple;
  85.   randomize;
  86.   doublebuffered := true;
  87.   timer1.enabled := false;
  88.   for c :=  1 to 20 do begin
  89.     r[c] := 20;
  90.     mx[c] := random(image1.width);
  91.     my[c] := random(image1.height);
  92.     vx[c] := random(10);
  93.     vy[c] := random(10);
  94.   end;
  95. end;
  96.  
  97. procedure TForm1.FormShowHint(Sender: TObject; HintInfo: PHintInfo);
  98. begin
  99.  
  100. end;
  101.  
  102. procedure TForm1.Image1Click(Sender: TObject);
  103. begin
  104.  
  105. end;
  106.  
  107. procedure TForm1.Timer1Timer(Sender: TObject);
  108. begin
  109.   with image1.canvas do begin
  110.     for c := 1 to 20 do begin
  111.       pen.color := clblack;
  112.       brush.color:=clblack;
  113.       ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  114.       mx[c]:=mx[c]+vx[c];
  115.       my[c]:=my[c]+vy[c];
  116.       pen.color := clpurple;
  117.       brush.color := clpurple;
  118.       ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  119.     end;
  120.   end;
  121.  
  122.  
  123.  
  124.   for c:= 1 to 20 do begin
  125.     if my[c]+r[c]>=image1.height
  126.     then vy[c]:= -vy[c];
  127.     if mx[c]+r[c]>=image1.width
  128.     then vx[c]:=-vx[c];
  129.     if my[c]-r[c]<0
  130.     then vy[c]:=-vy[c];
  131.     if mx[c]-r[c]<0
  132.     then vx[c]:=-vx[c];
  133.   end;
  134.  
  135.  
  136.  
  137.  
  138.  end;
  139.  
  140.  
  141.  
  142.  
  143. end.
  144.  

if you have any questions with the formulation of my question then feel free to ask!

regards
brady
Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 11, 2018, 02:57:05 pm
I can't compile your code. I got this error:
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 03:10:03 pm
questions:
do i need two of those? so switch1 and switch2?
You need to 'switch' (better worded swap) the movement of the two circles. No idea what you would like to do in a hypothetical second switch.
Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 03:11:40 pm
hey,

Quote
I can't compile your code. I got this error:
that is because (x, x) and (y, y) is missing behind the both "switch".

here is the code u can execute but it isnt doing what i want:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     Button2: TButton;
  18.     Image1: TImage;
  19.     Image2: TImage;
  20.     Timer1: TTimer;
  21.     Timer2: TTimer;
  22.     procedure Button1Click(Sender: TObject);
  23.     procedure Button2Click(Sender: TObject);
  24.     procedure FormCreate(Sender: TObject);
  25.     procedure FormShowHint(Sender: TObject; HintInfo: PHintInfo);
  26.     procedure Image1Click(Sender: TObject);
  27.     procedure Timer1Timer(Sender: TObject);
  28.   private
  29.  
  30.   public
  31.  
  32.   end;
  33.  
  34. var
  35.   Form1: TForm1;
  36.   mx : array[1..20] of integer;
  37.   my : array[1..20] of integer;
  38.   vx : array[1..20] of integer;
  39.   vy : array[1..20] of integer;
  40.   r  : array[1..20] of integer;
  41.   zwischenspeicher1, zwischenspeicher2, c, c2,j,i,d : integer;
  42.  
  43.  
  44. implementation
  45.  
  46. {$R *.lfm}
  47.  
  48. { TForm1 }
  49.  
  50. procedure TForm1.Button1Click(Sender: TObject);
  51. begin
  52.   timer1.enabled := true;
  53. end;
  54.  
  55. procedure TForm1.Button2Click(Sender: TObject);
  56. begin
  57.   timer1.enabled := false;
  58. end;
  59.  
  60. procedure switch (Var a,b:integer);
  61. var zwischenspeicher : integer;
  62.   begin
  63.     zwischenspeicher := a;
  64.     a := b;
  65.     b := zwischenspeicher;
  66.   end;
  67.  
  68.  
  69. procedure pythagoras;
  70.   var d : real;
  71.   var j,i, vx, vy : integer;
  72. begin
  73.   for j := 1 to 20 do
  74.     for i := 2 to 20 do begin
  75.     d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  76.     if d <= r[j]+r[i]+12 then begin
  77.     switch(vx, vx);
  78.     switch(vy, vy);
  79.   end;
  80.  end;
  81. end;
  82.  
  83. procedure TForm1.FormCreate(Sender: TObject);
  84. begin
  85.  
  86.   form1.color:=clpurple;
  87.   randomize;
  88.   doublebuffered := true;
  89.   timer1.enabled := false;
  90.   for c :=  1 to 20 do begin
  91.     r[c] := 20;
  92.     mx[c] := random(image1.width);
  93.     my[c] := random(image1.height);
  94.     vx[c] := random(10);
  95.     vy[c] := random(10);
  96.   end;
  97. end;
  98.  
  99. procedure TForm1.FormShowHint(Sender: TObject; HintInfo: PHintInfo);
  100. begin
  101.  
  102. end;
  103.  
  104. procedure TForm1.Image1Click(Sender: TObject);
  105. begin
  106.  
  107. end;
  108.  
  109. procedure TForm1.Timer1Timer(Sender: TObject);
  110. begin
  111.   with image1.canvas do begin
  112.     for c := 1 to 20 do begin
  113.       pen.color := clblack;
  114.       brush.color:=clblack;
  115.       ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  116.       mx[c]:=mx[c]+vx[c];
  117.       my[c]:=my[c]+vy[c];
  118.       pen.color := clpurple;
  119.       brush.color := clpurple;
  120.       ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  121.     end;
  122.   end;
  123.  
  124.  
  125.  
  126.   for c:= 1 to 20 do begin
  127.     if my[c]+r[c]>=image1.height
  128.     then vy[c]:= -vy[c];
  129.     if mx[c]+r[c]>=image1.width
  130.     then vx[c]:=-vx[c];
  131.     if my[c]-r[c]<0
  132.     then vy[c]:=-vy[c];
  133.     if mx[c]-r[c]<0
  134.     then vx[c]:=-vx[c];
  135.   end;
  136.  
  137.  
  138.  
  139.  
  140.  end;
  141.  
  142.  
  143.  
  144.  
  145. end.
  146.  

regards
brady

Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 03:12:28 pm
hey,

questions:
do i need two of those? so switch1 and switch2?
You need to 'switch' (better worded swap) the movement of the two circles. No idea what you would like to do in a hypothetical second switch.

okay thanks.

regards
brady

Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 03:28:28 pm
@bradyhartsfield:
I can this see going the wrong way because of interpretation difference.

Using two "switches" as your last code showed, does justify calling switch twice. However, you need to swap the movements inside your arrays.
Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 11, 2018, 03:55:51 pm
I found many bugs in the code. Give me some time, I will write a detail bug fixes and suggestions.
Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 03:59:45 pm
I found many bugs in the code. Give me some time, I will write a detail bug fixes and suggestions.

okay thank you!

regards
brady
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 04:30:30 pm
why is there at the part with the two "r`s" summed up a "+12" at the end?
That becomes clear when you remove the addition  ;)

A word of warning though. The whole idea of this assignment (besides applying the math and turning that into code) is that when you start out with implementing this (as something that appears easy to implement) that it becomes obvious that things are not quite work out as intended. There are minor flaws in the design/approach from the start. That is what the assignment is trying to teach you. You would need to apply more and better math to get rid of those flaws, and you can make that as complicated as you wish. The more accuracy you want the more code you would have to add and/or does make you realize that taking another approach might perhaps be better suited.

The latter is perhaps something that your teacher is going to address in class.
Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 11, 2018, 04:33:04 pm
why is there at the part with the two "r`s" summed up a "+12" at the end?
That becomes clear when you remove the addition  ;)

Not enough, the code still buggy.

As usually I will write a detail step-by-step explanation.
Be patient.  :)
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 04:37:43 pm
Not enough, the code still buggy.
Yes, i know  :). but TS is starting to get on the right track (seeing from where it all started). That TS is allowed to use events in a pascal program but not records... a choice/restriction i will never understand though as it makes things much easier to read/understand.

Quote
As usually I will write a detail step-by-step explanation.
Yes, thank you for that.

Quote
Be patient.  :)
I will. If not i would already have posted my (not 100% accurate and using record) code on the third or fourth post when TS started this topic in the other thread  :)
Title: Re: double loop for a program with the pythagoras
Post by: taazz on January 11, 2018, 04:44:17 pm
Code: Pascal  [Select][+][-]
  1. procedure pythagoras;
  2.   var d : real;
  3.   var j,i, vx, vy : integer;
  4. begin
  5.   for j := 1 to 20 do
  6.     for i := 2 to 20 do begin
  7.     d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  8.     if d <= r[j]+r[i]+12 then begin
  9.     vx[j] := -vx[j];
  10.     vy[j] := -vy[j];
  11.   end;
  12.  end;
  13. end;
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 05:02:12 pm
Code: Pascal  [Select][+][-]
  1.     vx[j] := -vx[j];
  2.     vy[j] := -vy[j];
  3.  
Very interesting attempt on elastic collision....
Title: Re: double loop for a program with the pythagoras
Post by: taazz on January 11, 2018, 05:06:20 pm
Code: Pascal  [Select][+][-]
  1.     vx[j] := -vx[j];
  2.     vy[j] := -vy[j];
  3.  
Very interesting attempt on elastic collision....
Not exactly correct I know but it shows the problem with the current approach.
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 05:15:18 pm
Not exactly correct I know but it shows the problem with the current approach.
Fair enough  :)

Indeed it shows what's going wrong. I have hard time grasping how it is possible not to note the difference.
Title: Step 1 - Remove Useless Items
Post by: Handoko on January 11, 2018, 05:20:45 pm
Step 1 - Remove Useless Items

These should be removed:
- Image2
- Timer2
- Global variables: zwischenspeicher1, zwischenspeicher2, c, c2, j, i, d

Note:
Good programmers usually avoid using global variables, use global variable only when you really need it.

Because variable c has been removed from global scope, now add the variable c it into:
- Procedure TForm1.FormCreate
- Procedure TForm1.Timer1Timer

This code still buggy. But you can download the code for comparison. I also formatted the code to make it more readable.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Image1: TImage;
  18.     Timer1: TTimer;
  19.     procedure Button1Click(Sender: TObject);
  20.     procedure Button2Click(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure Timer1Timer(Sender: TObject);
  23.   end;
  24.  
  25. var
  26.   Form1 : TForm1;
  27.   mx    : array[1..20] of integer;
  28.   my    : array[1..20] of integer;
  29.   vx    : array[1..20] of integer;
  30.   vy    : array[1..20] of integer;
  31.   r     : array[1..20] of integer;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TForm1 }
  38.  
  39. procedure TForm1.Button1Click(Sender: TObject);
  40. begin
  41.   Timer1.Enabled := True;
  42. end;
  43.  
  44. procedure TForm1.Button2Click(Sender: TObject);
  45. begin
  46.   Timer1.Enabled := False;
  47. end;
  48.  
  49. procedure switch (Var a,b:integer);
  50. var
  51.   zwischenspeicher: Integer;
  52. begin
  53.   zwischenspeicher := a;
  54.   a := b;
  55.   b := zwischenspeicher;
  56. end;
  57.  
  58. procedure pythagoras;
  59. var
  60.   d: Real;
  61.   j,i, vx, vy : Integer;
  62. begin
  63.   for j := 1 to 20 do
  64.     for i := 2 to 20 do begin
  65.       d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  66.       if d <= r[j]+r[i]+12 then begin
  67.         switch(vx, vx);
  68.         switch(vy, vy);
  69.       end;
  70.     end;
  71. end;
  72.  
  73. procedure TForm1.FormCreate(Sender: TObject);
  74. var
  75.   c: Integer;
  76. begin
  77.   Randomize;
  78.   Form1.Color    := clPurple;
  79.   DoubleBuffered := True;
  80.   Timer1.Enabled := False;
  81.   for c :=  1 to 20 do begin
  82.     r[c] := 20;
  83.     mx[c] := Random(Image1.Width);
  84.     my[c] := Random(Image1.Height);
  85.     vx[c] := Random(10);
  86.     vy[c] := Random(10);
  87.   end;
  88. end;
  89.  
  90. procedure TForm1.Timer1Timer(Sender: TObject);
  91. var
  92.   c: Integer;
  93. begin
  94.   with image1.canvas do begin
  95.     for c := 1 to 20 do begin
  96.       Pen.Color   := clBlack;
  97.       Brush.Color := clBlack;
  98.       Ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  99.       mx[c] := mx[c] + vx[c];
  100.       my[c] := my[c] + vy[c];
  101.       Pen.Color   := clPurple;
  102.       Brush.Color := clPurple;
  103.       Ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  104.     end;
  105.   end;
  106.   for c:= 1 to 20 do begin
  107.     if my[c]+r[c] >= Image1.Height then vy[c] := -vy[c];
  108.     if mx[c]+r[c] >= Image1.Width  then vx[c] := -vx[c];
  109.     if my[c]-r[c] < 0              then vy[c] := -vy[c];
  110.     if mx[c]-r[c] < 0              then vx[c] := -vx[c];
  111.   end;
  112. end;
  113.  
  114. end.
Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 05:22:22 pm
Code: Pascal  [Select][+][-]
  1. procedure pythagoras;
  2.   var d : real;
  3.   var j,i, vx, vy : integer;
  4. begin
  5.   for j := 1 to 20 do
  6.     for i := 2 to 20 do begin
  7.     d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  8.     if d <= r[j]+r[i]+12 then begin
  9.     vx[j] := -vx[j];
  10.     vy[j] := -vy[j];
  11.   end;
  12.  end;
  13. end;

i tried it like this:
Code: Pascal  [Select][+][-]
  1. procedure pythagoras;
  2. var c,g, vx, vy : integer;
  3.     d : real;
  4. begin
  5.   for c := 1 to 20 do
  6.   for g := 2 to 20 do begin
  7.     d := sqrt(sqr(mx[c]-mx[g])+sqr(my[c]-my[g]));
  8.     if d <= r[c]+r[g]+12 then begin
  9.     vx[c] := -vx[c];
  10.     vy[c] := -vy[c];
  11.   end;
  12.  end;
  13. end;
here i need to stay that i am using c and g now, because i just created a new project to try different things and i used c and g in that. anyways, if i try it like above there comes the error "Illegal qualifier" and the c from
Code: Pascal  [Select][+][-]
  1. vx[c] := -vx[c];
is marked red.

regards
brady

EDIT: i just saw the answer from Handoko, i will look at it now.
Title: Step 2 - Fixing the Procedure "pythagoras"
Post by: Handoko on January 11, 2018, 05:24:07 pm
Step 2 - Fixing the Procedure "pythagoras"

These are wrong:
switch(vx, vx);
switch(vy, vy);

It should be:
Code: Pascal  [Select][+][-]
  1. switch(vx[j], vx[i]);
  2. switch(vy[j], vy[i]);

Don't overlaps the for-loop. The correct for-loop is:
for j := 1 to 20 do
  for i := (j+1) to 20 do
 
Remove the extra +12 from the distance calculation:
Code: Pascal  [Select][+][-]
  1. r[j]+r[i]+12

Now remove the useless variables: vx, vy

Code: Pascal  [Select][+][-]
  1. procedure pythagoras;
  2. var
  3.   d: Real;
  4.   j,i: Integer;
  5. begin
  6.   for j := 1 to 20 do
  7.     for i := (j+1) to 20 do begin
  8.       d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  9.       if d <= r[j]+r[i] then begin
  10.         switch(vx[j], vx[i]);
  11.         switch(vy[j], vy[i]);
  12.       end;
  13.     end;
  14. end;
Title: Re: Step 1 - Remove Useless Items
Post by: bradyhartsfield on January 11, 2018, 05:26:21 pm
Step 1 - Remove Useless Items

These should be removed:
- Image2
- Timer2
- Global variables: zwischenspeicher1, zwischenspeicher2, c, c2, j, i, d

Note:
Good programmers usually avoid using global variables, use global variable only when you really need it.

Because variable c has been removed from global scope, now add the variable c it into:
- Procedure TForm1.FormCreate
- Procedure TForm1.Timer1Timer

This code still buggy. But you can download the code for comparison. I also formatted the code to make it more readable.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Image1: TImage;
  18.     Timer1: TTimer;
  19.     procedure Button1Click(Sender: TObject);
  20.     procedure Button2Click(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure Timer1Timer(Sender: TObject);
  23.   end;
  24.  
  25. var
  26.   Form1 : TForm1;
  27.   mx    : array[1..20] of integer;
  28.   my    : array[1..20] of integer;
  29.   vx    : array[1..20] of integer;
  30.   vy    : array[1..20] of integer;
  31.   r     : array[1..20] of integer;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TForm1 }
  38.  
  39. procedure TForm1.Button1Click(Sender: TObject);
  40. begin
  41.   Timer1.Enabled := True;
  42. end;
  43.  
  44. procedure TForm1.Button2Click(Sender: TObject);
  45. begin
  46.   Timer1.Enabled := False;
  47. end;
  48.  
  49. procedure switch (Var a,b:integer);
  50. var
  51.   zwischenspeicher: Integer;
  52. begin
  53.   zwischenspeicher := a;
  54.   a := b;
  55.   b := zwischenspeicher;
  56. end;
  57.  
  58. procedure pythagoras;
  59. var
  60.   d: Real;
  61.   j,i, vx, vy : Integer;
  62. begin
  63.   for j := 1 to 20 do
  64.     for i := 2 to 20 do begin
  65.       d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  66.       if d <= r[j]+r[i]+12 then begin
  67.         switch(vx, vx);
  68.         switch(vy, vy);
  69.       end;
  70.     end;
  71. end;
  72.  
  73. procedure TForm1.FormCreate(Sender: TObject);
  74. var
  75.   c: Integer;
  76. begin
  77.   Randomize;
  78.   Form1.Color    := clPurple;
  79.   DoubleBuffered := True;
  80.   Timer1.Enabled := False;
  81.   for c :=  1 to 20 do begin
  82.     r[c] := 20;
  83.     mx[c] := Random(Image1.Width);
  84.     my[c] := Random(Image1.Height);
  85.     vx[c] := Random(10);
  86.     vy[c] := Random(10);
  87.   end;
  88. end;
  89.  
  90. procedure TForm1.Timer1Timer(Sender: TObject);
  91. var
  92.   c: Integer;
  93. begin
  94.   with image1.canvas do begin
  95.     for c := 1 to 20 do begin
  96.       Pen.Color   := clBlack;
  97.       Brush.Color := clBlack;
  98.       Ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  99.       mx[c] := mx[c] + vx[c];
  100.       my[c] := my[c] + vy[c];
  101.       Pen.Color   := clPurple;
  102.       Brush.Color := clPurple;
  103.       Ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  104.     end;
  105.   end;
  106.   for c:= 1 to 20 do begin
  107.     if my[c]+r[c] >= Image1.Height then vy[c] := -vy[c];
  108.     if mx[c]+r[c] >= Image1.Width  then vx[c] := -vx[c];
  109.     if my[c]-r[c] < 0              then vy[c] := -vy[c];
  110.     if mx[c]-r[c] < 0              then vx[c] := -vx[c];
  111.   end;
  112. end;
  113.  
  114. end.

Okay, i did that, i have football training now, will be online in about two and a half hours.
Thank you for helping!

regards
brady
Title: Step 3 - Fix Procedure Timer1Timer
Post by: Handoko on January 11, 2018, 05:27:11 pm
Step 3 - Fix Procedure Timer1Timer

You have procedure pythagoras for calculating and doing the bouncing but you forgot to put it in Timer1Timer. So put it at the very beginning of TForm1.Timer1Timer.

I saw you draw a black circle to clear the old circle position. It is very wrong for doing animations especially games. It may work (sometimes) but it usually has bad effect. On your case, I can clearly see some black shadow appears on wrong circles (because you did not do z-order calculation)

The solution is to clear the whole screen before start painting the other things:
Pen.Color   := clBlack;
Brush.Color := clBlack;
Clear;

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   c: Integer;
  4. begin
  5.   pythagoras;
  6.   with image1.canvas do begin
  7.     Pen.Color   := clBlack;
  8.     Brush.Color := clBlack;
  9.     Clear;
  10.     for c := 1 to 20 do begin
  11.       mx[c] := mx[c] + vx[c];
  12.       my[c] := my[c] + vy[c];
  13.       Pen.Color   := clPurple;
  14.       Brush.Color := clPurple;
  15.       Ellipse(mx[c]-r[c], my[c]-r[c], mx[c]+r[c], my[c]+r[c]);
  16.     end;
  17.   end;
  18.   for c:= 1 to 20 do begin
  19.     if my[c]+r[c] >= Image1.Height then vy[c] := -vy[c];
  20.     if mx[c]+r[c] >= Image1.Width  then vx[c] := -vx[c];
  21.     if my[c]-r[c] < 0              then vy[c] := -vy[c];
  22.     if mx[c]-r[c] < 0              then vx[c] := -vx[c];
  23.   end;
  24. end;
Title: Step 4 - Some Minor Improvements
Post by: Handoko on January 11, 2018, 05:36:28 pm
Step 4 - Some Minor Improvements

Set anchoring for the image and resize the form, add these code into TFrom1.FormCreate:
Image1.Anchors := [akTop, akLeft, akRight, akBottom];
Width  := 800;
Height := 600;

In your Timer1Timer, you can merge to those 2 for-loops together:
for i := 1 to 20 do begin         

I saw you use variable c for looping. Usually programmers use i (and then j, k, ...). So change all those variables' names. By doing so, your code will look like written by a pro.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Image1: TImage;
  18.     Timer1: TTimer;
  19.     procedure Button1Click(Sender: TObject);
  20.     procedure Button2Click(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure Timer1Timer(Sender: TObject);
  23.   end;
  24.  
  25. var
  26.   Form1 : TForm1;
  27.   mx    : array[1..20] of Integer;
  28.   my    : array[1..20] of Integer;
  29.   vx    : array[1..20] of Integer;
  30.   vy    : array[1..20] of Integer;
  31.   r     : array[1..20] of Integer;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TForm1 }
  38.  
  39. procedure TForm1.Button1Click(Sender: TObject);
  40. begin
  41.   Timer1.Enabled := True;
  42. end;
  43.  
  44. procedure TForm1.Button2Click(Sender: TObject);
  45. begin
  46.   Timer1.Enabled := False;
  47. end;
  48.  
  49. procedure switch (var a, b: Integer);
  50. var
  51.   zwischenspeicher: Integer;
  52. begin
  53.   zwischenspeicher := a;
  54.   a := b;
  55.   b := zwischenspeicher;
  56. end;
  57.  
  58. procedure pythagoras;
  59. var
  60.   d: Real;
  61.   i, j: Integer;
  62. begin
  63.   for i := 1 to 20 do
  64.     for j := (i+1) to 20 do begin
  65.       d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
  66.       if d <= r[i]+r[j] then begin
  67.         switch(vx[i], vx[j]);
  68.         switch(vy[i], vy[j]);
  69.       end;
  70.     end;
  71. end;
  72.  
  73. procedure TForm1.FormCreate(Sender: TObject);
  74. var
  75.   i: Integer;
  76. begin
  77.   Randomize;
  78.   Image1.Anchors := [akTop, akLeft, akRight, akBottom];
  79.   Width  := 800;
  80.   Height := 600;
  81.   Color  := clPurple;
  82.   DoubleBuffered := True;
  83.   Timer1.Enabled := False;
  84.   for i :=  1 to 20 do begin
  85.     r[i] := 20;
  86.     mx[i] := Random(Image1.Width);
  87.     my[i] := Random(Image1.Height);
  88.     vx[i] := Random(10);
  89.     vy[i] := Random(10);
  90.   end;
  91. end;
  92.  
  93. procedure TForm1.Timer1Timer(Sender: TObject);
  94. var
  95.   i: Integer;
  96. begin
  97.   pythagoras;
  98.   with image1.canvas do begin
  99.     Pen.Color   := clBlack;
  100.     Brush.Color := clBlack;
  101.     Clear;
  102.     for i := 1 to 20 do begin
  103.       mx[i] := mx[i] + vx[i];
  104.       my[i] := my[i] + vy[i];
  105.       if my[i]+r[i] >= Image1.Height then vy[i] := -vy[i];
  106.       if mx[i]+r[i] >= Image1.Width  then vx[i] := -vx[i];
  107.       if my[i]-r[i] < 0              then vy[i] := -vy[i];
  108.       if mx[i]-r[i] < 0              then vx[i] := -vx[i];
  109.       Pen.Color   := clPurple;
  110.       Brush.Color := clPurple;
  111.       Ellipse(mx[i]-r[i], my[i]-r[i], mx[i]+r[i], my[i]+r[i]);
  112.     end;
  113.   end;
  114. end;
  115.  
  116. end.
Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 11, 2018, 05:40:08 pm
Now, the code should work like what you want.

But, there still 2 serious bugs:
- Balls sticking together
- Ball sticking at the edge

Well I know how to solve the issues above. I ever wrote Arcanoid and I got these issues too. But if I don't think you're now ready for it, so I think it is enough here now.
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 05:47:16 pm
Thank you Handoko !

I think the first order of business was for TS to get some  moving balls on his form. Now TS is able to spot the inaccuracies and think on how to address those.

@TS:
Code can still be improved a little (without directly addressing remaining issues), but you probably have (other) restrictions that prevent form doing so.

One thing you can address though is making use of globals (yes, now it is allowed  :) ) to define the number of balls for easy customization or as another example the max radius.

Also when i read this:
Code: [Select]
    mx[i] := Random(Image1.Width);
    my[i] := Random(Image1.Height);

Then ask yourself if that is correct. A picture tells more than a thousand words, so you will see soon enough what is wrong with that  ;)

edit: addressing the right person.
Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 11, 2018, 05:56:16 pm
Did you mean it should be:
Code: Pascal  [Select][+][-]
  1. mx[i] := Random(Image1.Width - 2*radius) + radius;
  2. my[i] := Random(Image1.Height - 2*radius) + radius;

And there was a bug in my code:
The Image1's size right after the form expanded does not has accurate values because the form has not 'actually' created so the calculation isn't accurate.
Title: Re: double loop for a program with the pythagoras
Post by: molly on January 11, 2018, 05:59:26 pm
Crêpes Suzette  :)

I should have been more careful in my post. those where meant for TS, not you Handoko  :-[

But, yes that is exactly what i meant  :)
Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 11, 2018, 09:57:06 pm
Hey,

thanks for all your help!

Now i have one more question:
Quote
Set anchoring for the image and resize the form, add these code into TFrom1.FormCreate:
Image1.Anchors := [akTop, akLeft, akRight, akBottom];
Width  := 800;
Height := 600;
for what is that? because i dont just want to copy but to understand why i am doing things.

regards
Nick


Title: Re: double loop for a program with the pythagoras
Post by: Handoko on January 12, 2018, 03:27:54 am
Set the width and height of the form. The anchors is to set the image to automatic grow larger or smaller if its parent (the form) resized.
Title: Re: double loop for a program with the pythagoras
Post by: bradyhartsfield on January 12, 2018, 06:12:29 pm
Hey,

ah okay, my program is now working! thank you all for your help and especially handoko for that step by step tutorial.

regards,
brady
Title: Re: double loop for a program with the pythagoras
Post by: Kays on January 18, 2018, 07:21:05 pm
[…]
Code: Pascal  [Select][+][-]
  1. d := sqrt(sqr(mx[j]-mx[i])+sqr(my[j]-my[i]));
FYI, you can shorten/simplify that expression with Math.hypot (https://freepascal.org/docs-html/current/rtl/math/hypot.html) to
Code: Pascal  [Select][+][-]
  1. d := hypot(mx[j]-mx[i], my[j]-my[i]);
TinyPortal © 2005-2018