### Author Topic: collision detection  (Read 3509 times)

#### shs

• Sr. Member
• Posts: 310
##### Re: collision detection
« Reply #15 on: October 12, 2017, 01:49:36 pm »
oh no these balls don't bounce i'm going to control the ball with the keyboard. so i just want the ball 2 to attached behind ball 1 in direction of travel.

also i tried this code but doesn't work

Code: Pascal  [Select]
1. distance := sqrt((sqr(x2-x1))+(sqr(y2-y1)));

#### molly

• Hero Member
• Posts: 1960
##### Re: collision detection
« Reply #16 on: October 12, 2017, 02:03:14 pm »
oh no these balls don't bounce i'm going to control the ball with the keyboard. so i just want the ball 2 to attached behind ball 1 in direction of travel.
Ah ok, static. in that case, have another look at J-G's answer:

If you're dealing with 'balls' then you need to keep the distance between the 'centres' always the same - ie. the sum of their radii (in case they are not the same diameter).

Your knowledge of geometry will be a deciding factor as to whether you can achieve your objective.
I think i should download/check RAW's example to see in what context you are calculating things.

#### rvk

• Hero Member
• Posts: 2945
##### Re: collision detection
« Reply #17 on: October 12, 2017, 02:27:48 pm »
Just wondering... is this still for the snake???

For instance... if you change the snake-elements to Ellipse() instead of Rectangle() you get attached effect.

Code: Pascal  [Select]
1.           Snake: begin
2.                    Canvas.Pen.Color := shape1.brush.color;
3.                    Canvas.Brush.Color := clwhite;
4.                    // Canvas.Rectangle(ScreenX, ScreenY, ScreenX+Scale, ScreenY+Scale);
5.                    Canvas.Ellipse(ScreenX, ScreenY, ScreenX+Scale, ScreenY+Scale);
6.                  end;

#### molly

• Hero Member
• Posts: 1960
##### Re: collision detection
« Reply #18 on: October 12, 2017, 02:32:11 pm »
Just in case it's not snake-related, a small examples using shapes (as per RAW's initial example)
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.
10. type
11.   { TForm1 }
12.
13.   TForm1 = class(TForm)
14.     procedure FormCreate(Sender: TObject);
15.     procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
16.   private
17.     { private declarations }
18.     Balls : array of TShape;
19.   public
20.     { public declarations }
21.   end;
22.
23. var
24.   Form1: TForm1;
25.
26. implementation
27.
28. {\$R *.lfm}
29.
30. uses
31.   LCLType;
32.
33. { TForm1 }
34.
35. procedure TForm1.FormCreate(Sender: TObject);
36. var
37.   i : integer;
38.   x : Integer = 200;
39. begin
40.   SetLength(Balls, 3);
41.   for i := low(Balls) to High(Balls) do
42.   begin
43.     Balls[i] := TShape.Create(Self);
44.     Balls[i].Parent := Self;
45.     Balls[i].Shape  := stCircle;
46.     Balls[i].Width  := 50;
47.     Balls[i].Height := 50;
48.     Balls[i].Top := 100;
49.     Balls[i].Left := x;
50.     x := x - Balls[i].Width;
51.   end;
52. end;
53.
54. procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
55. var
56.   i : integer;
57. begin
58.   if (Key = VK_DOWN) then
59.   begin
60.     for i := Low(Balls) to High(Balls) do Balls[i].Top := Balls[i].Top + 1;
61.   end
62.   else
63.   if (Key = VK_UP) then
64.   begin
65.     for i := Low(Balls) to High(Balls) do Balls[i].Top := Balls[i].Top - 1;
66.   end;
67. end;
68.
69. end.
70.

#### shs

• Sr. Member
• Posts: 310
##### Re: collision detection
« Reply #19 on: October 12, 2017, 03:04:07 pm »
@rvk
no it's not but thank you for asking

also guys can you help me with this code? i think i will get what i want if i fix this code
Code: Pascal  [Select]
1. distance := sqrt((sqr(x2-x1))+(sqr(y2-y1)));
so i want the distance between 2 balls to be equall which is radius + radius all the time.

#### rvk

• Hero Member
• Posts: 2945
##### Re: collision detection
« Reply #20 on: October 12, 2017, 03:10:04 pm »
also guys can you help me with this code? i think i will get what i want if i fix this code
Code: Pascal  [Select]
1. distance := sqrt((sqr(x2-x1))+(sqr(y2-y1)));
so i want the distance between 2 balls to be equall which is radius + radius all the time.
This isn't much of the code.

First, in line 2, you overwrite the value you give to distance in line 1.

Maybe you should share some code and explain what distance exactly is.
If it's the distance from the center of one ball to the center of the other then radius+radius should be correct.

But what are you going to do with that value? (we can only speculate without your code)

#### molly

• Hero Member
• Posts: 1960
##### Re: collision detection
« Reply #21 on: October 12, 2017, 03:16:38 pm »
also guys can you help me with this code? i think i will get what i want if i fix this code
Context is missing so that there is no way to make sure things are calculated correctly inside your code. As mentioned by rvk, show some more context please.

Quote
so i want the distance between 2 balls to be equall which is radius + radius all the time.
A circle has a radius. It also has a diameter (2 x radius). If the circles have the same radius = same diameter then the distance between the center point of two circles (touching each other) is 1 x diameter (or 2 x radius).

So your last line is correct. But since ocntext is missing, we have no way of telling what goes wrong (if there is something going wrong to begin with)

#### shs

• Sr. Member
• Posts: 310
##### Re: collision detection
« Reply #22 on: October 12, 2017, 03:21:10 pm »
Code: Pascal  [Select]
1. var
2.   Form1: TForm1;
3.   x1,x2,y1,y2:valreal;
4.
5.
6. implementation
7.
8. {\$R *.lfm}
9.
10. { TForm1 }
11.
12. procedure TForm1.Timer1Timer(Sender: TObject);
13.
14. var
15.   distance: ValReal;
16. begin
17.    x1:=b1.left;
18.    x2:=b2.left;
19.    y1:=b1.top;
20.    y2:=b2.top;
21.
22.    distance:=30;
23.    distance:=sqrt((sqr(x2-x1))+(sqr(y2-y1)));
24.
25.    end;

this is my full code b1 and b2 are TShape
and i want those to distance to be 30 because the radius for each balls are 15

#### molly

• Hero Member
• Posts: 1960
##### Re: collision detection
« Reply #23 on: October 12, 2017, 03:31:01 pm »
As i showed in my code (perhaps a bit hidden for you):
A shape does not have a radius, only a width and height (which corresponds to the diameter of the circle).
That means , if the width of your shape is 30 (circle radius becomes 15) then the distances bewteen two shapes should be 30 as well.

i do that in my code with the lines:
Code: Pascal  [Select]
1. Balls[i].Left := x;
2. x := x - Balls[i].Width;
3.
.. in order to initialize the positions of the shapes.

Then when you animate you would have to change the top positions (b1.top and b2.top) of both your shapes (add to go down, subtract to go up). In case you wish to move the shapes from left to right (or the other way around) then you would need to add/subtract from the shapes left position (b1.left and b2.left)

In case you would want to place your second shape situated at the left of your first shape then your code could look like:
Code: [Select]
`procedure TForm1.Timer1Timer(Sender: TObject);begin  b2.Left := b1.Left - b1.width;end;`
In case you would want to place your second shape situated at the right of your first shape then your code could look like:
Code: [Select]
`procedure TForm1.Timer1Timer(Sender: TObject);begin  b2.Left := b1.Left + b1.width;end;`
edit: i've adjusted my example to match you b1 and b2 shapes (which must be placed at design-time on the form). The event s can be added at design-time, so the only thing left for you to do is to match the code.

Btw, i have no idea why you would use a timer at this point inside your code, as you would like to 'move' your shapes by pressing keys (but perhaps i misunderstood the original intention of your code).
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.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     B1: TShape;
16.     B2: TShape;
17.     procedure FormCreate(Sender: TObject);
18.     procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
19.   private
20.     { private declarations }
21.   public
22.     { public declarations }
23.   end;
24.
25. var
26.   Form1: TForm1;
27.
28. implementation
29.
30. {\$R *.lfm}
31.
32. uses
33.   LCLType;
34.
35. { TForm1 }
36.
37. procedure TForm1.FormCreate(Sender: TObject);
38. // Initialize shapes, positions and widths
39. const
40.   distance = 30;
41. var
42.   xpos : Integer = 200;
43. begin
44.   B1.Shape  := stCircle; B2.Shape  := stCircle;
45.   B1.Width  := distance; B2.Width  := distance;
46.   B1.Height := distance; B2.Height := distance;
47.   B1.Top    := 100;      B2.Top    := 100;
48.   B1.Left   := xpos;
49.   // Place Shape B2 at left of Shape B1
50.   B2.Left   := xpos - B1.Width;
51.   // You could also have written:
52.   // B2.Left   := xpos - distance;
53. end;
54.
55.
56. procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
57. Const
58.   PixelSpeedDistance = 2;
59. begin
60.   // Move both shapes down PixelSpeedDistance pixels
61.   if (Key = VK_DOWN) then
62.   begin
63.     B1.Top := B1.Top + PixelSpeedDistance;
64.     B2.Top := B2.Top + PixelSpeedDistance;
65.   end
66.   else
67.   // Move both shapes up PixelSpeedDistance pixels
68.   if (Key = VK_UP) then
69.   begin
70.     B1.Top := B1.Top - PixelSpeedDistance;
71.     B2.Top := B2.Top - PixelSpeedDistance;
72.   end;
73. end;
74.
As you can probably see for yourself: if you have initialized your shapes to match your conditions then there is hardly anything left to code when you want to move your shapes up/down.
« Last Edit: October 12, 2017, 04:09:22 pm by molly »

#### User137

• Hero Member
• Posts: 1732
##### Re: collision detection
« Reply #24 on: October 12, 2017, 06:17:40 pm »
so i want the distance between 2 balls to be equall which is radius + radius all the time.
So you have 2 circles (technically not balls, because we are dealing with 2D not 3D) in positions p1 and p2. This is simplest to do with vector math, so both positions are vectors with x and y components. Say p2 is to follow p1, r is the radius of 1 circle;
Code: Pascal  [Select]
1. p2 = p1+2*r*normalize(p2-p1)

Additional bonus with normalize function from nxPascal. Because it needs to calculate sqrt, it can optionally return that too, but you can just pass in a nil
Code: Pascal  [Select]
1. procedure Norm(var x, y: single; const h: PSingle);
2. var _h: single;
3. begin
4.   _h:=hypot(x,y);
5.   if h<>nil then h^:=_h;
6.   if _h>0 then begin
7.     _h:=1/_h; x:=x*_h; y:=y*_h;
8.   end else begin
9.     x:=1; y:=0;
10.   end;
11. end;

#### Fungus

• Sr. Member
• Posts: 332
##### Re: collision detection
« Reply #25 on: October 12, 2017, 07:31:48 pm »
This sounds a bit like one of those "I do not want to make my (home)work, so I'll keep asking until I get working code" topics......

If you want ball2 to move as ball1, then you need to store the movement of ball1 in a circular array of TPoint's and move ball2 along the stored points. If you want ball2 to move at ball1 (sort of an elastic effect), then you will need to calculate the vector from ball2 to ball1 (subtract centers) and normalize that vector:

Code: Pascal  [Select]
1. vector_length = sqrt(sqr(vector.x)+sqr(vector.y));
2. normalized_vector.x = vector.x / vector_length;
3. normalized_vector.y = vector.y / vector_length;

Then you need to multiply the normalized vector with the speed of ball2. Should be fairly easy for the one who is interrested and not lazy!
« Last Edit: October 12, 2017, 07:46:12 pm by Fungus »

#### Handoko

• Hero Member
• Posts: 1730
• My goal: build my own game engine using Lazarus
##### Re: collision detection
« Reply #26 on: October 12, 2017, 07:55:02 pm »
Wow, you people are very nice. Lots of solutions, lots of formulas, lots of technical things.
I'm glad to see there are many nice people here.

But, I don't think the TS can understand what you're talking.
Do you think the TS know what are:
- division by zero
- differential equations
- inertia
- magnetic force
- vector
- normalize

You treat him like an experienced programmer but actually he still can't use array properly. Previously someone told him, his code has range check error and it seems he does not know how to solve it.

#### Fungus

• Sr. Member
• Posts: 332
##### Re: collision detection
« Reply #27 on: October 12, 2017, 08:16:02 pm »
@Handoko: We must assume basic knowledge of pascal programming, otherwise the topic would make no sense. And:

1) Any number divided with zero will cause an error since you cannot divide with nothing (2 / 0 = error, but 0 / 2 = 0).
2,3,4) OP should ignore these suggestions since they are out of scope (IMO).
5) A vector is a direction, the vector between two objects is extracted by subtracting the object's positions (to - from).
6) Normalization is done to ensure a vector length of one. This is useful when you want to apply speed to a vector (movement).

There ya' go!

#### shs

• Sr. Member
• Posts: 310
##### Re: collision detection
« Reply #28 on: October 13, 2017, 10:55:53 am »
thank you guys for the solution
i used this code and it works really well.
i ca
This sounds a bit like one of those "I do not want to make my (home)work, so I'll keep asking until I get working code" topics......

If you want ball2 to move as ball1, then you need to store the movement of ball1 in a circular array of TPoint's and move ball2 along the stored points. If you want ball2 to move at ball1 (sort of an elastic effect), then you will need to calculate the vector from ball2 to ball1 (subtract centers) and normalize that vector:

Code: Pascal  [Select]
1. vector_length = sqrt(sqr(vector.x)+sqr(vector.y));
2. normalized_vector.x = vector.x / vector_length;
3. normalized_vector.y = vector.y / vector_length;

Then you need to multiply the normalized vector with the speed of ball2. Should be fairly easy for the one who is interrested and not lazy!

i firstly created 3 balls on the form but it thought it would be better to create balls on oncreate procedure so i also created 3 balls to see if it works same as the other one.

the balls i created on the form seem to work better than the balls i created on oncreate

i don't know how to explain this so could you please find the attachment

please click the change label to control the other sets of balls

if you click array shape label you will be able to control the bigger balls and
if you click form shape you will be able to control the smaller balls

#### shs

• Sr. Member
• Posts: 310
##### Re: collision detection
« Reply #29 on: October 13, 2017, 03:11:32 pm »
can you guys suggest me what i should do to make the the array balls to move like form balls?