Recent

Author Topic: collision detection  (Read 28629 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)));
  2.    distance := radius+radius //they have same radius  

molly

  • Hero Member
  • *****
  • Posts: 2330
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: 6110
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: 2330
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)));
  2.    distance := radius+radius //they have same radius  
so i want the distance between 2 balls to be equall which is radius + radius all the time.

rvk

  • Hero Member
  • *****
  • Posts: 6110
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)));
  2.    distance := radius+radius //they have same radius  
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.

Second, what's wrong with distance := radius+radius ?

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: 2330
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: 2330
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: 1791
    • Nxpascal home
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: 353
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: 5130
  • My goal: build my own game engine using Lazarus
Re: collision detection
« Reply #26 on: October 12, 2017, 07:55:02 pm »
:D 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: 353
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?

 

TinyPortal © 2005-2018