Author Topic: 2D ball collisions without trigonometry.  (Read 21162 times)

0 Members and 1 Guest are viewing this topic.

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #30 on: May 17, 2021, 09:16:35 pm »
Some vector addition exercises.

vector addition  for 2 ball collisions with equal mass and velocity
********************************************

say, Red ball heading -1x, 0y towards 0, 0  (origin)

say, Cyan ball heading  1x, -1y towards 0, 0  (origin)

add the ball vectors

first reverse signs

red ball =  1x, 0y
cyan ball = -1x, 1y

add the reversed ball vectors
1x+-1x,  0y+ 1y = 0x, 1y (mvector)

mvector is wrong (in this case)  because cyan ball velocity is greater than red ball velocity

 The directions of the red ball -1x, 0y and cyan ball 1x, 1y are correct but their magnitudes are not equal.
the solution is to match the red ball velocity with the cyan ball velocity

 Red ball is now  -2^.5x, 0y

cyan ball the same as before  1x, -1y

try again - first reverse signs

red ball = 2^.5x, 0y
cyan ball = -1x, 1y

add the reversed ball vectors
2^.5x-1x,  0y+ 1y = 0.4142135x, 1y (mvector)

 what angle is that?

 arc tan 0.4142135 = 22.5 degrees

The new ball directions are:

 Red ball vector after collision
 -2^.5x, + 0.4142135x,  0y +  1y    =  -1x,   1 y    (balls have the same final velocity)

 Cyan ball vector after collision
 1x, + 0.4142135x,  -1y +  1y    =  1.4142135x,   0y  (balls have the same final velocity)

 which should be correct if the strike angle is 22.5 degrees. In other words,
 if a line through both ball centers at collision is at a right angle to mvector

*****
With 2 balls of unequal velocity and everything else the same, the direction of mvector will change.  It looks like the difference in velocity is somehow related to a rotation of mvector.  The case where the strike angle agrees with mvector (a line through both ball centers at collision is at a right angle to mvector) was for normalized ball velocities.   

If the ball directions are maintained but the velocities are different then there is a rotation of mvector as respects strike angle agreement.

It is not known if this rotation of mvector represents the correct final ball vectors due to a difference in velocity only.



« Last Edit: May 17, 2021, 10:33:42 pm by NOVARSEG »

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #31 on: May 17, 2021, 11:10:56 pm »
I think the missing element is the balls center positions at contact. You reference "origin", but they can't both occupy (0, 0). There would be no vector from which to obtain a perpendicular movement vector. Not to mention that they would occupy the same point in space...

This is a condensed version of the algorithm I've been working on, using the terms you posted. It seems to work with my billiard ball impacts and yields a unit vector for each ball to exit the collision. Changing the impact positions (redpos & cyanpos) will give the appropriate direction for each ball. That direction can then be scaled up by whatever speeds are determined by further processing. Using the dot product calculation, there is no need to match velocities. Dot product can also handle the force transference.
Code: QB64: [Select]
  1. TYPE V2
  2.     x AS SINGLE
  3.     y AS SINGLE
  4.  
  5. DIM AS V2 redmov, cyanmov, mvec, redpos, cyanpos, strike
  6.  
  7. 'These are the approach vectors you give
  8. redmov.x = -1: redmov.y = 0
  9. cyanmov.x = 1: cyanmov.y = -1
  10.  
  11. 'The important part is, where are the balls when they make contact. This determines the strike vector between them
  12. 'choosing arbitrary points of contact... change these around to see the effect to verify its accuracy
  13. redpos.x = 2: redpos.y = 2
  14. cyanpos.x = 1: cyanpos.y = 1
  15.  
  16. strike.x = cyanpos.x - redpos.x
  17. strike.y = cyanpos.y - redpos.y
  18. ShearOrthoUnit mvec, redmov, strike
  19. PRINT "red exits at <"; mvec.x; ", "; mvec.y; ">"
  20.  
  21. strike.x = redpos.x - cyanpos.x
  22. strike.y = redpos.y - cyanpos.y
  23. ShearOrthoUnit mvec, cyanmov, strike
  24. PRINT "cyan exits at <"; mvec.x; ", "; mvec.y; ">"
  25.  
  26. SUB ShearOrthoUnit (nv AS V2, in AS V2, stk AS V2)
  27.  
  28.     DIM AS V2 or1, or2
  29.     VecNorm stk '                                               normalize the strike vector
  30.     or1.x = stk.y: or1.y = -stk.x '                             obtain two potential orthogonal vectors {or1 & or2} of strike
  31.     or2.x = -stk.y: or2.y = stk.x
  32.     dot = VecDot(in, or1) '                                     dot product one of them with the incoming vector
  33.     nv.x = -or2.x * (dot < 0) - stk.x * (dot = 0) - or1.x * (dot > 0) 'exit vector x component
  34.     nv.y = -or2.y * (dot < 0) - stk.y * (dot = 0) - or1.y * (dot > 0) 'exit vector y component
  35.  
  36. END SUB 'ShearOrthoUnit
  37.  
  38.  
  39. SUB VecNorm (var AS V2)
  40.  
  41.     m = SQR(var.x * var.x + var.y * var.y)
  42.     IF m = 0 THEN
  43.         var.x = 0: var.y = 0 '                                  vector with magnitude 0 is a zero vector
  44.     ELSE
  45.         var.x = var.x / m: var.y = var.y / m '                  convert var to unit vector
  46.     END IF
  47.  
  48. END SUB 'VecNorm
  49.  
  50.  
  51. FUNCTION VecDot (var AS V2, var2 AS V2)
  52.  
  53.     VecDot = var.x * var2.x + var.y * var2.y '                  get dot product of var & var2
  54.  
  55. END FUNCTION 'VecDot
  56.  
  57.  

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #32 on: May 18, 2021, 12:01:54 am »
Quote
You reference "origin", but they can't both occupy (0, 0). There would be no vector from which to obtain a perpendicular movement vector. Not to mention that they would occupy the same point in space...

that is correct. I tried  to get around that with "point masses" but that was too abstract.  The ball direction are on a line that crosses 0, 0. The size of the balls (i like 40 pixel radius) determines the magnitude in this case the normal velocity is 80 pixels (per hour?)

The strike vector,  can be referenced to another vector (like mvector) because the strike vector passes through 0x, 0y.  It is somewhat an abstract idea but I don't have any other way of relating mvector to strike angle / vector. I should mention that mvector passes through 0x , 0y as well.


I ran your code  using

red ball   -2^.5x, 0y heading   towards  0, 0

cyan ball  -1x,  1y   heading towards 0, 0

and got different results

Forgot to set the strike vectors
To make this easier Im  gonna use pixels

red ball   -80 , 0y heading   towards  0, 0

cyan ball  (3200^.5) x, -(3200^.5) y   heading towards 0, 0

strike.x = 73.9103 pixels
strike.y = 30.6146 pixels

arc tan 30.6146 / 73.9103 = 22.5 degrees

in this case the strike vector is at a right angle to mvector.  I don't think there is any vector rotation to correct for in this case.

Red ball vector after collision
   =  -(3200^.5) x,  3200^.5 y   ?

 Cyan ball vector after collision
  =  80x,   0y   ?

your code gives different results
 






« Last Edit: May 18, 2021, 12:38:11 am by NOVARSEG »

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #33 on: May 18, 2021, 08:14:38 am »
Ugg, it would appear that the code I posted either has a bug, or my math is screwy. I plugged these numbers in: red (-80, 0)   cyan (3200 ^ .5, -(3200 ^ .5))

red ball   -80 , 0y heading   towards  0, 0

cyan ball  (3200^.5) x, -(3200^.5) y   heading towards 0, 0

and got identical exit vectors <-.3826834, -.9238796> for both balls, which should not have happened. The result should have been swapped components and signs from one ball to the other. Embarrassing to do that, I'd much rather be helpful than a distraction. Oh well, back to the drawing board...



On a point of terminology, forgive me if I'm a bit confused by your usage in the above.
I'm used to conceiving vectors as either position references (x, y) relative to origin (0, 0), or to other positions, or as magnitude/speed/force types <x, y> which may exist and be manipulated without reference to positional data.

A red ball at position (-80, 0) moving toward (0, 0) would have a magnitude/speed/force vector <0 - (-80)x, 0 - 0y> or <80, 0>. This would 'seem' to be how you're using the terms by saying "moving towards".

If, on the other hand the red ball is moving along <-80, 0> a reference to origin shouldn't be necessary for the vector math, except as updating a position after all force vectors are calculated, scaled and added to a previous position.


Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #34 on: May 18, 2021, 06:05:33 pm »
Quote
A red ball at position (-80, 0) moving toward (0, 0) would have a magnitude/speed/force vector <0 - (-80)x, 0 - 0y> or <80, 0>. This would 'seem' to be how you're using the terms by saying "moving towards".

I'm using balls with 40 pixel radius. That gives a normal velocity of 80

red ball heading  -80x, 0y towards 0x , 0y

the magnitude or velocity of the red ball is

(80^2 + 0^2)^.5 = 80

It works out nicely with your strike.x and strike.y

(strike.x ^2 + strike.y ^2).5 = 80 if both balls head towards 0, 0.  The magnitude of strike vector is 80 because there are 80 pixels from ball center to ball center at collision.
The strike vector crosses 0, 0 and so does mvector.

The reference at 0, 0 seems to be necessary because mvector is actually vector addition using the  parallelogram method
where all vectors can start at 0, 0 if you want.
« Last Edit: May 18, 2021, 06:15:13 pm by NOVARSEG »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #35 on: May 18, 2021, 06:49:40 pm »
I haven't been following the thread but am just wondering, what is the benefit of no/without trigorometry?  Seems you can always convert between the trig and vector/sqrt/etc equivalent, perhaps not always easily.  FYI, Bill is the original QB-no-Trig:  https://www.tapatalk.com/groups/qbasic/rotation-t29617.html#p172877

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #36 on: May 18, 2021, 07:22:34 pm »
probably no benefit, maybe a bit faster ? 

I have resorted to trig just to get this all sorted out.  I still have no proof the mvector method works or not. How can it be proven?

« Last Edit: May 19, 2021, 01:10:26 am by NOVARSEG »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #37 on: May 19, 2021, 12:02:06 pm »
Thanks to @OldMoses  link to paper I finally have decent ball action for Pool Game! As collision demo'd here in this thread:
https://www.qb64.org/forum/index.php?topic=3866.msg132377#msg132377

Can check out Pool code at Steve's forum here (no images all hand drawn)
https://qb64.freeforums.net/thread/150/pool
« Last Edit: May 19, 2021, 02:00:00 pm by bplus »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #38 on: May 19, 2021, 10:32:27 pm »
bplus

say red ball heads -80x, 0y towards 0x, 0y and blue ball heads  0x, -80y  towards 0x, 0y. In this case there is 90 degrees between ball headings and both balls have equal velocity

For the simplest case, vector addition using the parallelogram method simply bisects the angle between red ball and blue ball.  mvector is located on this bisection line.   However for this bisection to occur requires the strike vector to be at right angle to the bisection line

calculate mvector

first reverse signs of balls
red ball  80x, 0y
blue ball   0x, 80y

vector addition

80x +0x,, 0y + 80y = 80x,  80y

so the mvector, in this case, is at a 45 degree angle in the upper right quadrant which is the angle of the bisection line.
now calculate final ball vectors (after collision)
(add original ball vectors to mvector)

red ball
-80x + 80x ,  0y + 80y =   0x, 80y

blue ball
0x + 80x ,  -80y + 80y =   80x, 0y

Are the final vectors correct?


 
« Last Edit: May 19, 2021, 10:37:14 pm by NOVARSEG »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #39 on: May 20, 2021, 12:22:59 am »
A red ball heading east towards point 0,0 and blue heading north to 0,0 both equal distance away and equal speed will meet and kiss at tangent angle 45 /225 degree before 0,0 due to their radii and red will deflect North and blue deflect east. I demo'd this or something similar in special case collisions, this thread.

Here is demo for this from tiny mod of previous code in this thread:
Code: QB64: [Select]
  1. _Title "From Paper 2 Ball Collision with Vectors,  press r to restart" 'B+ 2021-05-13
  2. ' Collision tests based on Paper       https://www.vobarian.com/collisions/2dcollisions2.pdf
  3. ' The vector functions are modifications of tsh73 JB code converted to QB64 by me.
  4. ' earlier code 2 Ball Collision with Vectors by Arrow Addition ' B+ 2021-05-10
  5. ' 2021-05-10  fixed arrow so points from base x,y To angle
  6. ' from Collision Study #4   press spacebar to toggle tracer" ' b+ 2021-05-09
  7.  
  8. ' !!!!!!!!!!!!!!!! Adjust Ball according to experiment 2 is always good
  9.  
  10. Const Balls = 2 '<<<<<<<<< change this to 2 to test special case setups: head on, parallel and perpendicular
  11. 'Const Balls = 5 '<<<<<<<<< the more the balls the more problems pop up for Random Numbers experiments
  12. '                            no more than 20! because have to start all balls not overlapping any other
  13.  
  14.  
  15. Const Xmax = 600 ' screen width
  16. Const Ymax = 600 ' screen height
  17. Const R = 50 '     balls radii
  18. Const R22 = R * R * 4 ' save some time with (2 * R) * (2 * R)
  19.  
  20. Const MV_Speed = 45 ' magnitude of Force Arrow say it's constant for simplicity sake
  21. Type Ball
  22.     As Long x, y
  23.     As Double dx, dy, a ' dx, dy = change x, y axis
  24.     As _Unsigned Long colr
  25.  
  26. Screen _NewImage(Xmax, Ymax, 32)
  27. _Delay .25
  28. ' these can be static as no balls added or subtracted in closed system
  29. Dim As Ball b(1 To Balls), nf(1 To Balls) ' b() is current frame balls data , nf( ) is for next frame balls data
  30. Dim As Long clrMode, i, j, rdm
  31. b(1).colr = &HFFFF0000 'red ball 1 is red
  32. b(2).colr = &HFF0000FF 'blue ball 2 is blue
  33. clrMode = 1
  34. Dim v1$, v2$, dv1$, dv2$, dv1u$, dv2u$, norm$, unitNorm$, unitTan$ 'vectors
  35. Dim vp1n$, vp1t$, vp2n$, vp2t$ ' post collision vectors
  36. Dim As Double v1n, v1t, v2n, v2t ' dot products
  37. Dim As Double vp1n, vp1t, vp2n, vp2t ' post collision dot products
  38. restart:
  39. 'horizontal collisions  Head On
  40. 'b(1).dx = 5
  41. 'b(1).dy = 0 ' b1 is just moving on x axis to the right at 5 pixels per frame
  42. 'b(2).dx = -5
  43. 'b(2).dy = 0 ' b2 is just moving on x axis to the left at 5 pixels per frame
  44. 'b(1).x = 300 - 5 * b(1).dx - R ' in 5 frames b1 will meet b2  kiss at center of screen
  45. 'b(1).y = 300
  46. 'b(2).x = 300 - 5 * b(2).dx + R ' in 5 frames b1 will meet b2  kiss at center of screen
  47. 'b(2).y = 300
  48.  
  49. 'vertical collisions  Head On
  50. 'b(1).dy = 5
  51. 'b(1).dx = 0 ' b1 is just moving on x axis to the right at 5 pixels per frame
  52. 'b(2).dy = -5
  53. 'b(2).dx = 0 ' b2 is just moving on x axis to the left at 5 pixels per frame
  54. 'b(1).y = 300 - 5 * b(1).dy - R ' in 5 frames b1 will meet b2  kiss at center of screen
  55. 'b(1).x = 300
  56. 'b(2).y = 300 - 5 * b(2).dy + R ' in 5 frames b1 will meet b2  kiss at center of screen
  57. 'b(2).x = 300
  58.  
  59. ' 45 & 135 collsions   Head On
  60. 'b(1).dy = 5
  61. 'b(1).dx = 5 ' b1 is just moving on x axis to the right at 5 pixels per frame
  62. 'b(2).dy = -5
  63. 'b(2).dx = -5 ' b2 is just moving on x axis to the left at 5 pixels per frame
  64. 'b(1).y = 300 - 5 * b(1).dy - R ' in 5 frames b1 will meet b2  kiss at center of screen
  65. 'b(1).x = 300 - 5 * b(1).dx - R
  66. 'b(2).y = 300 - 5 * b(2).dy + R ' in 5 frames b1 will meet b2  kiss at center of screen
  67. 'b(2).x = 300 - 5 * b(2).dx + R
  68.  
  69. ' Parallel and converging paths
  70. 'b(1).dy = -6
  71. 'b(1).dx = 1 ' b1 is just moving on x axis to the right at 5 pixels per frame
  72. 'b(2).dy = -6
  73. 'b(2).dx = -1 ' b2 is just moving on x axis to the left at 5 pixels per frame
  74. 'b(1).y = Ymax - R ' in 5 frames b1 will meet b2  kiss at center of screen
  75. 'b(1).x = 300 - 20 * b(1).dx - R
  76. 'b(2).y = Ymax - R ' in 5 frames b1 will meet b2  kiss at center of screen
  77. 'b(2).x = 300 - 20 * b(2).dx + R
  78.  
  79. ' Perpendicular and 90 degree collision   should be just before mid screen
  80. b(1).dy = 0
  81. b(1).dx = -5
  82. b(2).dy = -5
  83. b(2).dx = 0
  84. b(1).y = 300
  85. b(1).x = Xmax - R
  86. b(2).y = Ymax - R ' north
  87. b(2).x = 300
  88.  
  89. ' random assignments
  90. 'For i = 1 To Balls
  91. '    tryAgain:
  92. '    Print i
  93. '    b(i).x = rand&(R, Xmax - R)
  94. '    b(i).y = rand&(R, Ymax - R)
  95. '    For j = 1 To i - 1
  96. '        If _Hypot(b(i).x - b(j).x, b(i).y - b(j).y) < R + R Then GoTo tryAgain
  97. '    Next
  98. '    b(i).dx = (Rnd * 4 + 1) * rdir
  99. '    b(i).dy = (Rnd * 4 + 1) * rdir
  100. '    rdm = rand&(1, 7)
  101. '    If rdm < 1 Or rdm > 7 Then Beep
  102. '    Select Case rdm
  103. '        Case 1: b(i).colr = _RGB32(Rnd * 200 + 55, 0, 0)
  104. '        Case 2: b(i).colr = _RGB32(0, Rnd * 100 + 55, 0)
  105. '        Case 3: b(i).colr = _RGB32(0, 0, Rnd * 200 + 55)
  106. '        Case 4: b(i).colr = &HFFFF6600
  107. '        Case 5: b(i).colr = &HFFFF0088
  108. '        Case 6: b(i).colr = &HFF00FF88
  109. '        Case 7: b(i).colr = _RGB32(Rnd * 200 + 55, Rnd * 200 + 55, Rnd * 200 + 55)
  110. '    End Select
  111. 'Next
  112.  
  113. While _KeyDown(27) = 0
  114.     Dim k$
  115.     k$ = InKey$
  116.     If Len(k$) Then
  117.         If Asc(k$) = 32 Then clrMode = -1 * clrMode
  118.         If Asc(k$) = 27 And Len(k$) = 1 Then End
  119.         If k$ = "r" Then GoTo restart
  120.     End If
  121.     If clrMode > 0 Then Cls
  122.     Circle (300, 300), 2
  123.     For i = 1 To Balls ' draw balls then  update for next frame
  124.  
  125.         ' this just draw the balls with arrows pointing to their headings
  126.         Circle (b(i).x, b(i).y), R, b(i).colr
  127.         b(i).a = _Atan2(b(i).dy, b(i).dx)
  128.         ArrowTo b(i).x, b(i).y, b(i).a, MV_Speed, &HFFFFFF00
  129.         ' debug
  130.         '_PrintString (b(i).x - 8, b(i).y - 8), _Trim$(Right$("00" + Str$(i), 2)) 'all the balls weren't getting colored
  131.  
  132.         ' check for collision
  133.         Dim cd, saveJ
  134.         cd = 100000: saveJ = 0
  135.         For j = 1 To Balls 'find deepest collision in case more than one we want earliest = deepest penetration
  136.             If i <> j Then
  137.                 Dim dx, dy
  138.                 dx = b(i).x - b(j).x: dy = b(i).y - b(j).y
  139.                 If dx * dx + dy * dy <= R22 Then ' collision but is it first or deepest collision
  140.                     If R22 - dx * dx + dy * dy < cd Then cd = R22 - dx * dx + dy * dy: saveJ = j
  141.                 End If
  142.             End If
  143.         Next
  144.         If cd <> 100000 Then ' found collision change ball i dx, dy   calc new course for ball i
  145.  
  146.             ''reflection  from circle  using Vectors  from JB, thanks tsh73
  147.             v1$ = vect$(b(i).x, b(i).y) ' circle i
  148.             v2$ = vect$(b(saveJ).x, b(saveJ).y) ' the other circle j
  149.             dv1$ = vect$(b(i).dx, b(i).dy) ' change in velocity vector
  150.             dv2$ = vect$(b(saveJ).dx, b(saveJ).dy)
  151.             dv1u$ = vectUnit$(dv1$) '1 pixel
  152.             dv2u$ = vectUnit$(dv2$)
  153.             'Print dv$, cv$, dv0$   ' check on things
  154.             '_Display
  155.             'Sleep
  156.             Do ' this should back up the balls to kiss point thanks tsh73
  157.                 v1$ = vectSub$(v1$, dv1u$)
  158.                 v2$ = vectSub(v2$, dv2u$)
  159.             Loop While vectLen(vectSub$(v1$, v2$)) < R + R 'back up our circle i to point on kiss
  160.             ''now, get reflection speed
  161.             ''radius to radius, norm is
  162.             norm$ = vectSub$(v1$, v2$) ' this to this worked without all between from that collision paper
  163.  
  164.             '  step 1 unit norm and tangent
  165.             unitNorm$ = vectUnit$(norm$)
  166.             unitTan$ = vect$(-vectY(unitNorm$), vectX(unitNorm$))
  167.             ' step 2 v$ and cv$ are 2 ball vectors (locations)  done already
  168.             ' step 3 dot products before collision projecting onto normal and tangent vectors
  169.             v1n = vectDotProduct(dv1$, unitNorm$)
  170.             v1t = vectDotProduct(dv1$, unitTan$)
  171.             v2n = vectDotProduct(dv2$, unitNorm$)
  172.             v2t = vectDotProduct(dv2$, unitTan$)
  173.             ' step 4 simplest  post collision dot products
  174.             vp1t = v1t
  175.             vp2t = v2t
  176.             ' step 5  simplified by m = 1 for both balls just swap the numbers
  177.             vp1n = v2n
  178.             vp2n = v1n
  179.             ' step 6  vp vectors mult the n, t numbers by unit vectors
  180.             vp1n$ = vectScale$(vp1n, unitNorm$)
  181.             vp1t$ = vectScale$(vp1t, unitTan$)
  182.             vp2n$ = vectScale$(vp2n, unitNorm$)
  183.             vp2t$ = vectScale$(vp2t, unitTan$)
  184.             'step  7  add the 2 vectors n and t
  185.             dv1$ = vectAdd$(vp1n$, vp1t$)
  186.  
  187.             ' to this  now just switch tangent and norm
  188.             'dv1$ = vectSub$(vectNorm$(dv1$, norm$), vectTangent$(dv1$, norm$)) 'to this
  189.  
  190.             ' store in next frame array
  191.             nf(i).dx = vectX(dv1$)
  192.             nf(i).dy = vectY(dv1$)
  193.  
  194.         Else ' no collision
  195.             nf(i).dx = b(i).dx
  196.             nf(i).dy = b(i).dy
  197.         End If
  198.         'update location of ball next frame
  199.         nf(i).x = b(i).x + nf(i).dx
  200.         nf(i).y = b(i).y + nf(i).dy
  201.  
  202.         ' check in bounds next frame
  203.         If nf(i).x < R Then nf(i).dx = -nf(i).dx: nf(i).x = R
  204.         If nf(i).x > Xmax - R Then nf(i).dx = -nf(i).dx: nf(i).x = Xmax - R
  205.         If nf(i).y < R Then nf(i).dy = -nf(i).dy: nf(i).y = R
  206.         If nf(i).y > Ymax - R Then nf(i).dy = -nf(i).dy: nf(i).y = Ymax - R
  207.     Next
  208.  
  209.     ''now that we've gone through all old locations update b() with nf() data
  210.     For i = 1 To Balls
  211.         b(i).x = nf(i).x: b(i).y = nf(i).y
  212.         b(i).dx = nf(i).dx: b(i).dy = nf(i).dy
  213.     Next
  214.     ' next frame ready to draw
  215.     _Display
  216.     _Limit 30
  217. 'Cls   ' debug why aren't all the balls getting colored
  218. 'For i = 1 To Balls
  219. '    Print i, b(i).colr
  220. 'Next
  221.  
  222.  
  223. Function rand& (lo As Long, hi As Long) ' fixed?
  224.     rand& = Int(Rnd * (hi - lo) + 1) + lo
  225.  
  226. Function rdir ()
  227.     If Rnd < .5 Then rdir = -1 Else rdir = 1
  228.  
  229.  
  230.  
  231. Sub ArrowTo (BaseX As Long, BaseY As Long, rAngle As Double, lngth As Long, colr As _Unsigned Long)
  232.     Dim As Long x1, y1, x2, y2, x3, y3
  233.     x1 = BaseX + lngth * Cos(rAngle)
  234.     y1 = BaseY + lngth * Sin(rAngle)
  235.     x2 = BaseX + .8 * lngth * Cos(rAngle - _Pi(.05))
  236.     y2 = BaseY + .8 * lngth * Sin(rAngle - _Pi(.05))
  237.     x3 = BaseX + .8 * lngth * Cos(rAngle + _Pi(.05))
  238.     y3 = BaseY + .8 * lngth * Sin(rAngle + _Pi(.05))
  239.     Line (BaseX, BaseY)-(x1, y1), colr
  240.     Line (x1, y1)-(x2, y2), colr
  241.     Line (x1, y1)-(x3, y3), colr
  242.  
  243. ' convert some vector functions from JB, turns out much easier to use string functions to pass vectors
  244. ' than using SUBs to do vector calcs
  245.  
  246. Function vect$ (x, y) ' convert x, y to string for passing vectors with Functions
  247.     vect$ = _Trim$(Str$(x)) + "," + _Trim$(Str$(y))
  248.  
  249. Function vectX (v$)
  250.     vectX = Val(LeftOf$(v$, ","))
  251.  
  252. Function vectY (v$)
  253.     vectY = Val(RightOf$(v$, ","))
  254.  
  255. Function vectLen (v$)
  256.     Dim x, y
  257.     x = Val(LeftOf$(v$, ","))
  258.     y = Val(RightOf$(v$, ","))
  259.     vectLen = Sqr(x * x + y * y)
  260.  
  261. Function vectUnit$ (v$)
  262.     Dim x, y, vl
  263.     x = Val(LeftOf$(v$, ","))
  264.     y = Val(RightOf$(v$, ","))
  265.     vl = Sqr(x * x + y * y)
  266.     vectUnit$ = vect$(x / vl, y / vl)
  267.  
  268. Function vectAdd$ (v1$, v2$)
  269.     Dim x1, y1, x2, y2
  270.     x1 = Val(LeftOf$(v1$, ","))
  271.     y1 = Val(RightOf$(v1$, ","))
  272.     x2 = Val(LeftOf$(v2$, ","))
  273.     y2 = Val(RightOf$(v2$, ","))
  274.     vectAdd$ = vect$(x1 + x2, y1 + y2)
  275.  
  276. Function vectSub$ (v1$, v2$)
  277.     Dim x1, y1, x2, y2
  278.     x1 = Val(LeftOf$(v1$, ","))
  279.     y1 = Val(RightOf$(v1$, ","))
  280.     x2 = Val(LeftOf$(v2$, ","))
  281.     y2 = Val(RightOf$(v2$, ","))
  282.     vectSub$ = vect$(x1 - x2, y1 - y2)
  283.  
  284. Function vectDotProduct (v1$, v2$)
  285.     Dim x1, y1, x2, y2
  286.     x1 = Val(LeftOf$(v1$, ","))
  287.     y1 = Val(RightOf$(v1$, ","))
  288.     x2 = Val(LeftOf$(v2$, ","))
  289.     y2 = Val(RightOf$(v2$, ","))
  290.     vectDotProduct = x1 * x2 + y1 * y2
  291.  
  292. Function vectScale$ (a, v$) 'a * vector v$
  293.     Dim x, y
  294.     x = Val(LeftOf$(v$, ","))
  295.     y = Val(RightOf$(v$, ","))
  296.     vectScale$ = vect$(a * x, a * y)
  297.  
  298. Function vectTangent$ (v$, base$)
  299.     Dim n$
  300.     n$ = vectUnit$(base$)
  301.     vectTangent$ = vectScale$(vectDotProduct(n$, v$), n$)
  302.  
  303. Function vectNorm$ (v$, base$)
  304.     vectNorm$ = vectSub$(v$, vectTangent$(v$, base$))
  305.  
  306. ' update these 2 in case of$ is not found! 2021-02-13
  307. Function LeftOf$ (source$, of$)
  308.     If InStr(source$, of$) > 0 Then LeftOf$ = Mid$(source$, 1, InStr(source$, of$) - 1) Else LeftOf$ = source$
  309.  
  310. ' update these 2 in case of$ is not found! 2021-02-13
  311. Function RightOf$ (source$, of$)
  312.     If InStr(source$, of$) > 0 Then RightOf$ = Mid$(source$, InStr(source$, of$) + Len(of$)) Else RightOf$ = ""
  313.  
  314.  

You need to know not only their new headings but the points they are at when they kiss and change direction.

Quote
red ball
-80x + 80x ,  0y + 80y =   0x, 80y

blue ball
0x + 80x ,  -80y + 80y =   80x, 0y

Are the final vectors correct?

I would say no, though your vector system unrecognizable to me but blue is definitely traveling in -x direction and red in  -y direction as shown in demo after they collide.
« Last Edit: May 20, 2021, 12:34:31 am by bplus »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #40 on: May 20, 2021, 12:35:07 am »
Quote
red will deflect North and blue deflect east.

good we got the same answer!

Quote
You need to know not only their new headings but the points they are at when they kiss and change direction.

yep OldMoses calls it the strike vector.  And yes, red will deflect North and blue deflect east only if strike vector is at right angle to bisection line.

With the same headings, if the strike vector changes, then the mvector is no longer on the bisection line.
I'm working on some math to prove where mvector ends up when that happens.

I'm hoping that if mvector can be located /calculated properly then all the math of 2d ball collisions can be derived from mvector only
« Last Edit: May 20, 2021, 12:56:37 am by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #41 on: May 20, 2021, 12:51:06 am »
Quote
I would say no, though your vector system unrecognizable to me but blue is definitely traveling in -x direction and red in  -y direction as shown in demo after they collide.

if the red heads in a -y direction (after collision) that is south ?  how can that be if the blue was heading north before collision?

north = top of screen
west  = left of screen
east = right of screen
south = bottom of screen

my vector system is vector addition.  No dot  products - not yet anyway
« Last Edit: May 20, 2021, 01:00:29 am by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #42 on: May 20, 2021, 02:45:40 am »
Strike vector can be calculated from mvector (on bisection line). The magnitude of strike vector is 80 pixels because the ball radius is 40 pixels.  When the balls collide there is a distance of 80 pixels between ball centers which is the hypotenuse of the x, y  strike components

Code: QB64: [Select]
  1. DIM strikeX AS SINGLE
  2. DIM strikeY AS SINGLE
  3. DIM mvecX AS SINGLE
  4. DIM mvecY AS SINGLE
  5. DIM ballDIA AS INTEGER
  6. ballDIA = 80 'pixels
  7.  
  8. mvecX = 80 'x component of mvector (mvector on bisection line)
  9. mvecY = 80 'y component of mvector (mvector on bisection line)
  10.  
  11. strikeX = (ballDIA ^ 2 / (mvecX / mvecY + 1)) ^ .5
  12. PRINT "strikeX"; strikeX
  13.  
  14. strikeY = (ballDIA ^ 2 / (mvecY / mvecX + 1)) ^ .5
  15.  
  16. PRINT "strikeY"; strikeY
  17.  

 Working on math to calculate mvector from strike vector if mvector magnitude on bisection line is known.

Expecting the final ball velocities to vary with a change in strike vector

« Last Edit: May 20, 2021, 03:28:01 am by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #43 on: May 20, 2021, 04:18:25 am »
More code.  Ok not verified yet.  Have to run a simulation to see if there are any bugs. Introduced bvector which is mvector on bisection line.  bvecX and bvecY are set to 80.

Code: QB64: [Select]
  1. DIM strikeX AS SINGLE
  2. DIM strikeY AS SINGLE
  3. DIM bvecX AS SINGLE 'bvector is mvector on bisection line
  4. DIM bvecY AS SINGLE 'bvector is mvector on bisection line
  5. DIM mvecX AS SINGLE
  6. DIM mvecY AS SINGLE
  7. DIM bvecMAG AS SINGLE
  8. DIM strikeMAG AS INTEGER
  9. DIM ballRAD AS INTEGER 'ball radius in pixels
  10. ballRAD = 40 'pixels
  11. strikeMAG = 2 * ballRAD
  12.  
  13.  
  14. bvecX = 80 'mvector on bisection line
  15. bvecY = 80 'mvector on bisection line
  16. bvecMAG = (bvecX ^ 2 + bvecY ^ 2) ^ .5
  17.  
  18. strikeX = (strikeMAG ^ 2 / (bvecX ^ 2 / bvecY ^ 2 + 1)) ^ .5
  19. PRINT "strikeX"; strikeX
  20.  
  21. strikeY = (strikeMAG ^ 2 / (bvecY ^ 2 / bvecX ^ 2 + 1)) ^ .5
  22.  
  23. PRINT "strikeY"; strikeY
  24.  
  25. '*************  calculate mvector from strike vector and bvector
  26.  
  27. mvecX = (bvecMAG ^ 2 / (strikeX ^ 2 / strikeY ^ 2 + 1)) ^ .5
  28. mvecY = (bvecMAG ^ 2 / (strikeY ^ 2 / strikeX ^ 2 + 1)) ^ .5
  29.  
  30. PRINT "mvecX"; mvecX
  31. PRINT "mvecY"; mvecY
« Last Edit: May 20, 2021, 04:34:03 am by NOVARSEG »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 2D ball collisions without trigonometry.
« Reply #44 on: May 20, 2021, 01:08:31 pm »
if the red heads in a -y direction (after collision) that is south ?  how can that be if the blue was heading north before collision?

north = top of screen
west  = left of screen
east = right of screen
south = bottom of screen

my vector system is vector addition.  No dot  products - not yet anyway

Oh man! I still don't know my left and right or I should say my West from my East! Left Is heading West and moving to the right IS East.

I meant to say the Blue ball moving North will be deflected West, to the left.
and the Red ball moving West will be deflected North, up.

The demo is correct even if my description is wrong, sorry for making a difficult subject more confusing.

Vector addition should work, it was drilled into my head in Physics 101 College Course (for non Physics Majors that didn't do Calculus side by side with Physics like they do for Physics Majors which is so much better in my opinion).
But not drilled into my head was vectors that went at any angle even in degrees let alone radians!

To find which way a body will move you add up all the vector forces applied to the center of the body mass which for a ball is easiest to describe and find, its the origin of the circle.

And we drew arrows and placed the tail of one arrow at the head of the other for the "resultant" force an arrow from body center to head of the first arrow. That was as far as it got we did not have computers then just graduating from slide rules to hand calculators.

So these arrows have x, y components, add x components and y components yeah NOVARSEG you seem to be on right track so far.

But at moment of collision how do you calculate the force of the other ball acting on the first ball?

Don't you have to look at the angle the balls are at to each other, because the tangent line they will reflect from (just like light off a surface) is perpendicular to the angle the balls are at when they kiss. Angle in = Angle out off that tangent line at kiss point. Easy to describe a real b... to get mathematically!

Reflecting off a box boundary is piece of cake just reverse the dx or dy direction with a negative sign.
Bouncing off an angled surface not so fun because both dx, dy components are effected and most of the time unequally.

And in Basic Graphics  decreasing y is moving North and  increasing y is moving South another bug-a-boo obstacle to easy understanding and communication between math and science students and computer apps in Basic.

North is up in direction and y decreases to get there.
South is down direction and y increases to get there, it is Basic Fact of computer life face it or get out your Window command and fix your graphics to work as you learn it math or science class.

When you use Window command you have to know which graphics command can follow: line, circle (though you better check out arcs) pset these work with Window coordinate system. Mouse x, y doesn't work but does have a PMAP fix that comes with Basic read your Wiki carefully about WINDOW command.

« Last Edit: May 20, 2021, 01:38:40 pm by bplus »