Author Topic: Re: Ellastic Collisions  (Read 428 times)

0 Members and 1 Guest are viewing this topic.

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Ellastic Collisions
« on: March 28, 2019, 07:45:51 pm »
here's a blast from the past, containing my implementation of Elastic/Inelastic collisions. You may need to slow this appreciably on newer systems as it is FAST. Your creations are generally pretty darn cool, so here's one of my hits:
from: https://www.tapatalk.com/groups/qbasic/collider-worms-t30559.html

Code: QB64: [Select]
  1. '* this also makes a cool little screensaver
  2. '* this is a program i wrote just messing around, however, it follows all the physical laws concerning
  3. '* mass and elastic collisions. in order to show z-plane travel, i made the balls smaller according to a
  4. '* linear scale -- that is, that the farther the spheres are back in the z-plane (low z-numbers), the
  5. '* smaller the spere appears. to get a more accurate visual of this, use same-sized spheres, rather than
  6. '* randomly sized ones. also, in order to increase the likelihood of collisions, use a smaller z-plane distance
  7. '* or make it 2-d (either by setting the flag for 2d to true or eliminating the code referring to z-plane)
  8. '* v2 now features COR -- coefficient of restitution, which in a nutshell describes how "sticky" or "repulsive"
  9. '* an object is to collision. Low COR's essentially stick together (think steel ball colliding into soft butter), while
  10. '* high COR's bounce like steel balls off an equally hard steel floor. The COR must be a number from 0 to 1.
  11. '* same as before, works well for n=256 balls, but once past 1000, gets pretty syrupy. I just added the COR
  12. '* code today. So there you have it. Anyone who wants to add point light sources and do Phong shading can
  13. '* make this program REALLY shine, especially if they can make it run decently for n=16 ball system.
  14.  
  15. TYPE BallRec
  16. Radius AS DOUBLE
  17. Mass AS DOUBLE
  18. colr AS INTEGER
  19. const MaxScreenX=640
  20. const MinScreenX=0
  21. const MinScreenY=0
  22. const MaxScreenY=480
  23. const MinScreenZ=0
  24. const MaxScreenZ=100
  25. const Minvx=0
  26. const Maxvx=16
  27. const Minvy=0
  28. const Maxvy=16
  29. const Minvz=0
  30.  
  31. const Maxvz=16
  32. const aspectR=1
  33. schermo = _NEWIMAGE(Maxscreenx, Maxscreeny, 256)
  34. VIEW (Minscreenx, Minscreeny)-(Maxscreenx - 1, Maxscreeny - 1), 0
  35. NBalls% = 255
  36. DIM b(NBalls%) AS BallRec
  37. FOR i& = 0 TO NBalls%
  38. 'radius = RND * 16
  39. b(i&).px = Minscreenx + RND * (Maxscreenx - radius)
  40. b(i&).py = Minscreeny + RND * (Maxscreeny - radius)
  41. b(i&).pz = Minscreenz + RND * (Maxscreenz - radius)
  42. b(i&).vx = Minvx + RND * (Maxvx - Minvx) * (-1 ^ i& MOD 2)
  43. b(i&).vy = Minvy + RND * (Maxvy - Minvy) * (-1 ^ i& MOD 2)
  44. b(i&).vz = Minvz + RND * (Maxvz - Minvz) * (-1 ^ i& MOD 2)
  45. b(i&).Radius = 16 'INT(RND * 16) + 1
  46. b(i&).Mass = RND * 2 + 1
  47. b(i&).colr = INT(RND * 255) + 1
  48. b(i&).COR = INT(RND * 1)
  49. just2d% = -1
  50. FOR i& = 0 TO NBalls%
  51. FOR j& = 0 TO NBalls% - 1
  52. IF i& <> j& THEN
  53. IF b(i&).px + b(i&).vx - (b(j&).px + b(j&).vx) > b(i&).Radius + b(j&).Radius THEN
  54. IF b(i&).py + b(i&).vy - (b(j&).py + b(j&).vy) > b(i&).Radius + b(j&).Radius THEN
  55. IF (b(i&).pz + b(i&).vz - (b(j&).pz + b(j&).vz) <= b(i&).Radius + b(j&).Radius) AND (NOT just2d%) THEN
  56. ELSEIF NOT just2d% AND (b(i&).pz + b(i&).vz - (b(j&).pz + b(j&).vz) <= b(i&).Radius + b(j&).Radius) THEN
  57. CASE IS < 1 / 2
  58. CalcVelocities b(), i&, j&
  59. CalcVelocitiesCOR b(), i&, j&
  60. CIRCLE (b(i&).px, b(i&).py), (b(i&).Radius * b(i&).pz / Maxscreenz), b(i).colr, 0, 6.28, Aspectr
  61. IF b(i&).px + b(i&).vx < Minscreenx THEN
  62. b(i&).vx = -b(i&).vx
  63. ELSEIF b(i&).px + b(i&).vx > Maxscreenx THEN
  64. b(i&).vx = -b(i&).vx
  65. b(i&).px = b(i&).px + b(i&).vx
  66.  
  67. IF b(i&).py + b(i&).vy < Minscreeny THEN
  68. b(i&).vy = -b(i&).vy
  69. ELSEIF b(i&).py + b(i&).vy > Maxscreeny THEN
  70. b(i&).vy = -b(i&).vy
  71. b(i&).py = b(i&).py + b(i&).vy
  72.  
  73. IF b(i&).pz + b(i&).vz < Minscreenz THEN
  74. b(i&).vz = -b(i&).vz
  75. ELSEIF b(i&).pz + b(i&).vz > Maxscreenz THEN
  76. b(i&).vz = -b(i&).vz
  77. b(i&).pz = b(i&).pz + b(i&).vz
  78. CIRCLE (b(i&).px, b(i&).py), (b(i&).Radius * b(i&).pz / Maxscreenz), b(i&).colr, 0, 6.28, Aspectr
  79. PAINT (b(i&).px, b(i&).py), _RGB32(16 * b(i&).colr, 8 * b(i&).colr, b(i&).colr)
  80. k$ = INKEY$
  81. IF k$ > "" THEN
  82. SUB CalcVelocities (b() AS BallRec, i&, j&)
  83. temp1 = b(i&).vx
  84. temp2 = b(j&).vx
  85. totalMass = (b(i&).Mass + b(j&).Mass)
  86. b(i&).vx = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  87. b(j&).vx = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  88. temp1 = b(i&).vy
  89. temp2 = b(j&).vy
  90. b(i&).vy = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  91. b(j&).vy = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  92. temp1 = b(i&).vz
  93. temp2 = b(j&).vz
  94. b(i&).vz = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  95. b(j&).vz = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  96.  
  97. '* Normalize COR's of 2 objects to 1, otherwise Conservation of Momentum is violated -- adding energy to the closed system.
  98. '* According to the great physicists out there, roughly half of all collisions in a system are inelastic to some extent.
  99.  
  100. SUB CalcVelocitiesCOR (b() AS BallRec, i&, j&) ' * varying levels of elasticity from 0 (perfectly inelastic) to 1 (perfectly elastic)
  101. vx1 = b(i&).Mass * b(i&).vx + b(j&).Mass * b(j&).vx + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vx - b(j&).vx)
  102. vx2 = b(i&).Mass * b(i&).vx + b(j&).Mass * b(j&).vx + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vx - b(i&).vx)
  103. b(i&).vx = vx1
  104. b(j&).vx = vx2
  105. vy1 = b(i&).Mass * b(i&).vy + b(j&).Mass * b(j&).vy + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vy - b(j&).vy)
  106. vy2 = b(i&).Mass * b(i&).vy + b(j&).Mass * b(j&).vy + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vy - b(i&).vy)
  107. b(i&).vy = vy1
  108. b(j&).vy = vy2
  109. vz1 = b(i&).Mass * b(i&).vz + b(j&).Mass * b(j&).vz + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vz - b(j&).vz)
  110. vz2 = b(i&).Mass * b(i&).vz + b(j&).Mass * b(j&).vz + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vz - b(i&).vz)
  111. b(i&).vz = vz1
  112. b(j&).vz = vz2
  113.  

another variation that clears the screen between frames and uses fixed-size balls:
Code: QB64: [Select]
  1. '* this also makes a cool little screensaver
  2. '* this is a program i wrote just messing around, however, it follows all the physical laws concerning
  3. '* mass and elastic collisions. in order to show z-plane travel, i made the balls smaller according to a
  4. '* linear scale -- that is, that the farther the spheres are back in the z-plane (low z-numbers), the
  5. '* smaller the spere appears. to get a more accurate visual of this, use same-sized spheres, rather than
  6. '* randomly sized ones. also, in order to increase the likelihood of collisions, use a smaller z-plane distance
  7. '* or make it 2-d (either by setting the flag for 2d to true or eliminating the code referring to z-plane)
  8. '* v2 now features COR -- coefficient of restitution, which in a nutshell describes how "sticky" or "repulsive"
  9. '* an object is to collision. Low COR's essentially stick together (think steel ball colliding into soft butter), while
  10. '* high COR's bounce like steel balls off an equally hard steel floor. The COR must be a number from 0 to 1.
  11. '* same as before, works well for n=256 balls, but once past 1000, gets pretty syrupy. I just added the COR
  12. '* code today. So there you have it. Anyone who wants to add point light sources and do Phong shading can
  13. '* make this program REALLY shine, especially if they can make it run decently for n=16 ball system.
  14.  
  15. TYPE BallRec
  16.     px AS DOUBLE
  17.     py AS DOUBLE
  18.     pz AS DOUBLE
  19.     vx AS DOUBLE
  20.     vy AS DOUBLE
  21.     vz AS DOUBLE
  22.     Radius AS DOUBLE
  23.     Mass AS DOUBLE
  24.     colr AS INTEGER
  25.     COR AS DOUBLE
  26. CONST MaxScreenX = 640
  27. CONST MinScreenX = 0
  28. CONST MinScreenY = 0
  29. CONST MaxScreenY = 480
  30. CONST MinScreenZ = 0
  31. CONST MaxScreenZ = 100
  32. CONST Minvx = 0
  33. CONST Maxvx = 16
  34. CONST Minvy = 0
  35. CONST Maxvy = 16
  36. CONST Minvz = 0
  37.  
  38. CONST Maxvz = 16
  39. CONST aspectR = 1
  40. schermo = _NEWIMAGE(MaxScreenX, MaxScreenY, 256)
  41. VIEW (MinScreenX, MinScreenY)-(MaxScreenX - 1, MaxScreenY - 1), 0
  42. NBalls% = 511
  43. DIM b(NBalls%) AS BallRec
  44. FOR i& = 0 TO NBalls%
  45.     'radius = RND * 16
  46.     b(i&).px = MinScreenX + RND * (MaxScreenX - radius)
  47.     b(i&).py = MinScreenY + RND * (MaxScreenY - radius)
  48.     b(i&).pz = MinScreenZ + RND * (MaxScreenZ - radius)
  49.     b(i&).vx = Minvx + RND * (Maxvx - Minvx) * (-1 ^ i& MOD 2)
  50.     b(i&).vy = Minvy + RND * (Maxvy - Minvy) * (-1 ^ i& MOD 2)
  51.     b(i&).vz = Minvz + RND * (Maxvz - Minvz) * (-1 ^ i& MOD 2)
  52.     b(i&).Radius = INT(RND * 8) + 1
  53.     b(i&).Mass = RND * 2 + 1
  54.     b(i&).colr = INT(RND * 255) + 1
  55.     b(i&).COR = INT(RND * 1)
  56. just2d% = -1
  57.     CLS
  58.     FOR i& = 0 TO NBalls%
  59.         FOR j& = 0 TO NBalls% - 1
  60.             IF i& <> j& THEN
  61.                 IF b(i&).px + b(i&).vx - (b(j&).px + b(j&).vx) > b(i&).Radius + b(j&).Radius THEN
  62.                 ELSE
  63.                     IF b(i&).py + b(i&).vy - (b(j&).py + b(j&).vy) > b(i&).Radius + b(j&).Radius THEN
  64.                     ELSE
  65.                         IF (b(i&).pz + b(i&).vz - (b(j&).pz + b(j&).vz) <= b(i&).Radius + b(j&).Radius) AND (NOT just2d%) THEN
  66.                         ELSEIF NOT just2d% AND (b(i&).pz + b(i&).vz - (b(j&).pz + b(j&).vz) <= b(i&).Radius + b(j&).Radius) THEN
  67.                             SELECT CASE RND
  68.                                 CASE IS < 1 / 2
  69.                                     CalcVelocities b(), i&, j&
  70.                                 CASE ELSE
  71.                                     CalcVelocitiesCOR b(), i&, j&
  72.                             END SELECT
  73.                             EXIT FOR
  74.                         END IF
  75.                     END IF
  76.                 END IF
  77.             END IF
  78.         NEXT
  79.         CIRCLE (b(i&).px, b(i&).py), (b(i&).Radius * b(i&).pz / MaxScreenZ), b(i).colr, 0, 6.28, aspectR
  80.         IF b(i&).px + b(i&).vx < MinScreenX THEN
  81.             b(i&).vx = -b(i&).vx
  82.         ELSEIF b(i&).px + b(i&).vx > MaxScreenX THEN
  83.             b(i&).vx = -b(i&).vx
  84.         ELSE
  85.             b(i&).px = b(i&).px + b(i&).vx
  86.         END IF
  87.  
  88.         IF b(i&).py + b(i&).vy < MinScreenY THEN
  89.             b(i&).vy = -b(i&).vy
  90.         ELSEIF b(i&).py + b(i&).vy > MaxScreenY THEN
  91.             b(i&).vy = -b(i&).vy
  92.         ELSE
  93.             b(i&).py = b(i&).py + b(i&).vy
  94.         END IF
  95.  
  96.         IF b(i&).pz + b(i&).vz < MinScreenZ THEN
  97.             b(i&).vz = -b(i&).vz
  98.         ELSEIF b(i&).pz + b(i&).vz > MaxScreenZ THEN
  99.             b(i&).vz = -b(i&).vz
  100.         ELSE
  101.             b(i&).pz = b(i&).pz + b(i&).vz
  102.         END IF
  103.         CIRCLE (b(i&).px, b(i&).py), (b(i&).Radius * b(i&).pz / MaxScreenZ), b(i&).colr, 0, 6.28, aspectR
  104.         PAINT (b(i&).px, b(i&).py), _RGB32(16 * b(i&).colr, 8 * b(i&).colr, b(i&).colr)
  105.     NEXT
  106.     k$ = INKEY$
  107.     IF k$ > "" THEN
  108.         EXIT DO
  109.     END IF
  110.     _DISPLAY
  111. SUB CalcVelocities (b() AS BallRec, i&, j&)
  112.     temp1 = b(i&).vx
  113.     temp2 = b(j&).vx
  114.     totalMass = (b(i&).Mass + b(j&).Mass)
  115.     b(i&).vx = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  116.     b(j&).vx = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  117.     temp1 = b(i&).vy
  118.     temp2 = b(j&).vy
  119.     b(i&).vy = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  120.     b(j&).vy = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  121.     temp1 = b(i&).vz
  122.     temp2 = b(j&).vz
  123.     b(i&).vz = (temp1 * (b(i&).Mass - b(j&).Mass) + (2 * b(j&).Mass * temp2)) / totalMass
  124.     b(j&).vz = (temp2 * (b(j&).Mass - b(i&).Mass) + (2 * b(i&).Mass * temp1)) / totalMass
  125.  
  126. '* Normalize COR's of 2 objects to 1, otherwise Conservation of Momentum is violated -- adding energy to the closed system.
  127. '* According to the great physicists out there, roughly half of all collisions in a system are inelastic to some extent.
  128.  
  129. SUB CalcVelocitiesCOR (b() AS BallRec, i&, j&) ' * varying levels of elasticity from 0 (perfectly inelastic) to 1 (perfectly elastic)
  130.     vx1 = b(i&).Mass * b(i&).vx + b(j&).Mass * b(j&).vx + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vx - b(j&).vx)
  131.     vx2 = b(i&).Mass * b(i&).vx + b(j&).Mass * b(j&).vx + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vx - b(i&).vx)
  132.     b(i&).vx = vx1
  133.     b(j&).vx = vx2
  134.     vy1 = b(i&).Mass * b(i&).vy + b(j&).Mass * b(j&).vy + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vy - b(j&).vy)
  135.     vy2 = b(i&).Mass * b(i&).vy + b(j&).Mass * b(j&).vy + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vy - b(i&).vy)
  136.     b(i&).vy = vy1
  137.     b(j&).vy = vy2
  138.     vz1 = b(i&).Mass * b(i&).vz + b(j&).Mass * b(j&).vz + b(j&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(i&).vz - b(j&).vz)
  139.     vz2 = b(i&).Mass * b(i&).vz + b(j&).Mass * b(j&).vz + b(i&).Mass * ((b(i&).COR + b(j&).COR) / 2) * (b(j&).vz - b(i&).vz)
  140.     b(i&).vz = vz1
  141.     b(j&).vz = vz2
  142.  

« Last Edit: March 28, 2019, 07:57:51 pm by codeguy »

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Ellastic Collisions
« Reply #1 on: March 28, 2019, 08:04:55 pm »
Also of interest as this demo contains an implementation of my NSpace Collision Detection System as a SUB:
Code: QB64: [Select]
  1. _TITLE "NSpace Sub And Demo Code"
  2. '*NSpaceRoutine.bas
  3. TYPE RGBRec
  4.     red AS _UNSIGNED _BYTE
  5.     green AS _UNSIGNED _BYTE
  6.     blue AS _UNSIGNED _BYTE
  7.  
  8. TYPE Coord
  9.     x AS INTEGER
  10.     y AS INTEGER
  11.     z AS INTEGER
  12.  
  13. TYPE PointRec
  14.     x AS SINGLE
  15.     y AS SINGLE
  16.     z AS SINGLE
  17.     radius AS SINGLE
  18.     colorsRGB AS RGBRec
  19.     inc AS Coord
  20.     precalcRGB AS LONG
  21.     precalcdiameter AS LONG
  22.  
  23. TYPE Segment
  24.     xseg AS _UNSIGNED _BYTE
  25.     yseg AS _UNSIGNED _BYTE
  26.     zseg AS _UNSIGNED _BYTE
  27.     xsegsize AS _UNSIGNED _BYTE
  28.     ysegsize AS _UNSIGNED _BYTE
  29.     zsegsize AS _UNSIGNED _BYTE
  30.  
  31. TYPE ScreenRec
  32.     begins AS Coord
  33.     ends AS Coord
  34.  
  35. xscreen& = _SCREENIMAGE
  36. SCREEN xscreen&
  37. DIM GScrn AS ScreenRec
  38. GScrn.begins.x = 1
  39. GScrn.begins.y = 1
  40. GScrn.begins.z = 1
  41. GScrn.ends.x = _WIDTH(xscreen&)
  42. GScrn.ends.y = _HEIGHT(xscreen&)
  43. GScrn.ends.z = 1024
  44.  
  45. DIM a(16383 * 1.5) AS PointRec
  46. DIM SegmentMetrics AS Segment
  47. SegmentMetrics.xseg = 16
  48. SegmentMetrics.xsegsize = (GScrn.ends.x - GScrn.begins.x + 1) / SegmentMetrics.xseg
  49. SegmentMetrics.yseg = 16
  50. SegmentMetrics.ysegsize = (GScrn.ends.y - GScrn.begins.y + 1) / SegmentMetrics.yseg
  51. SegmentMetrics.zseg = 16
  52. SegmentMetrics.zsegsize = (GScrn.ends.z - GScrn.begins.z + 1) / SegmentMetrics.zseg
  53. REDIM NspaceObjects(SegmentMetrics.xseg, SegmentMetrics.yseg, SegmentMetrics.zseg, SizeOf(a()) / 4)
  54. REDIM counts%(SegmentMetrics.xseg, SegmentMetrics.yseg, SegmentMetrics.zseg)
  55. FOR i = LBOUND(a) TO UBOUND(a)
  56.     a(i).radius = (RND * 2) OR 1
  57.     a(i).precalcdiameter = a(i).radius * 2
  58.     a(i).x = a(i).radius + RND * (GScrn.ends.x - a(i).radius)
  59.     a(i).y = a(i).radius + RND * (GScrn.ends.y - a(i).radius)
  60.     a(i).z = a(i).radius + RND * (GScrn.ends.z - a(i).radius)
  61.     a(i).inc.x = (6 * (1 - RND * 2)) OR 1
  62.     a(i).inc.y = (6 * (1 - RND * 2)) OR 1
  63.     a(i).inc.z = (6 * (1 - RND * 2)) OR 1
  64.     a(i).colorsRGB.red = INT(RND * 256)
  65.     a(i).colorsRGB.green = INT(RND * 256)
  66.     a(i).colorsRGB.blue = INT(RND * 256)
  67.     a(i).precalcRGB = _RGB(a(i).colorsRGB.red, a(i).colorsRGB.green, a(i).colorsRGB.blue)
  68. frames& = 0
  69. lastframe& = 0
  70. Start! = TIMER(.001)
  71. xstart! = Start!
  72.  
  73.  
  74.     CLS
  75.     FOR i = LBOUND(a) TO UBOUND(a)
  76.         IF a(i).x - a(i).radius + a(i).inc.x < GScrn.begins.x THEN
  77.             a(i).inc.x = -a(i).inc.x
  78.         ELSEIF a(i).x + a(i).radius + a(i).inc.x > GScrn.ends.x THEN
  79.             a(i).inc.x = -a(i).inc.x
  80.         END IF
  81.         a(i).x = a(i).x + a(i).inc.x
  82.  
  83.         IF a(i).y - a(i).radius + a(i).inc.y < GScrn.begins.y THEN
  84.             a(i).inc.y = -a(i).inc.y
  85.         ELSEIF a(i).y + a(i).radius + a(i).inc.y > GScrn.ends.y THEN
  86.             a(i).inc.y = -a(i).inc.y
  87.         END IF
  88.         a(i).y = a(i).y + a(i).inc.y
  89.  
  90.         IF a(i).z - a(i).radius + a(i).inc.z < GScrn.begins.z THEN
  91.             a(i).inc.z = -a(i).inc.z
  92.         ELSEIF a(i).z + a(i).radius + a(i).inc.z > GScrn.ends.z THEN
  93.             a(i).inc.z = -a(i).inc.z
  94.         END IF
  95.         a(i).z = a(i).z + a(i).inc.z
  96.         PSET (a(i).x, a(i).y), a(i).precalcRGB
  97.     NEXT
  98.  
  99.     NSpace a(), GScrn, SegmentMetrics, NspaceObjects(), counts%()
  100.     FOR XLoop = 0 TO SegmentMetrics.xseg
  101.         FOR YLoop = 0 TO SegmentMetrics.yseg
  102.             FOR ZLoop = 0 TO SegmentMetrics.zseg
  103.                 FOR d% = 0 TO counts%(XLoop, YLoop, ZLoop) - 2
  104.                     m& = NspaceObjects(XLoop, YLoop, ZLoop, d%)
  105.                     FOR e% = d% + 1 TO counts%(XLoop, YLoop, ZLoop) - 1
  106.                         n& = NspaceObjects(XLoop, YLoop, ZLoop, e%)
  107.                         IF Collision%(a(m&), a(n&)) THEN
  108.                             a(n&).inc.x = -a(m&).inc.x
  109.                             a(n&).inc.y = -a(m&).inc.y
  110.                             a(n&).inc.z = -a(m&).inc.z
  111.                         END IF
  112.                     NEXT
  113.                 NEXT
  114.             NEXT
  115.         NEXT
  116.     NEXT
  117.  
  118.     REDIM counts%(SegmentMetrics.xseg, SegmentMetrics.yseg, SegmentMetrics.zseg)
  119.  
  120.     IF ABS(TIMER(.001) - Start!) < 2 THEN
  121.         frames& = frames& + 1
  122.     ELSE
  123.         Start! = TIMER(.001)
  124.         PRINT (frames& - lastframe&) / 2
  125.         lastframe& = frames&
  126.     END IF
  127.     _DISPLAY
  128.     d$ = INKEY$
  129. LOOP UNTIL d$ > ""
  130. finish! = TIMER(.001)
  131. PRINT frames& / (finish! - xstart!)
  132.  
  133. SUB NSpace (a() AS PointRec, Scrn AS ScreenRec, SegmentsXYZ AS Segment, NspaceObjects(), Counts%())
  134.     DIM xbox, ybox, zbox AS _UNSIGNED _BYTE
  135.     DIM oxseg, oyseg, ozseg AS _UNSIGNED _BYTE
  136.     FOR m& = LBOUND(A) TO UBOUND(A)
  137.         oxseg = a(m&).x \ SegmentsXYZ.xsegsize
  138.         oyseg = a(m&).y \ SegmentsXYZ.ysegsize
  139.         ozseg = a(m&).z \ SegmentsXYZ.zsegsize
  140.         IF Counts%(oxseg, oyseg, ozseg) > UBOUND(NspaceObjects, 4) THEN
  141.             REDIM _PRESERVE NspaceObjects(SegmentsXYZ.xseg, SegmentsXYZ.yseg, SegmentsXYZ.zseg, Counts%(oxseg, oyseg, ozseg))
  142.             '* PRINT Counts%(oxseg, oyseg, ozseg)
  143.         END IF
  144.         dx% = Counts%(oxseg, oyseg, ozseg)
  145.         NspaceObjects(oxseg, oyseg, ozseg, dx%) = m&
  146.         Counts%(oxseg, oyseg, ozseg) = dx% + 1
  147.         IF a(m&).radius THEN
  148.             FOR u = -a(m&).radius TO a(m&).radius STEP a(m&).precalcdiameter
  149.                 xbox = (a(m&).x + u) \ SegmentsXYZ.xsegsize
  150.                 IF xbox >= 0 THEN
  151.                     IF xbox <= SegmentsXYZ.xseg THEN
  152.                         ybox = (a(m&).y + u) \ SegmentsXYZ.ysegsize
  153.                         IF ybox >= 0 THEN
  154.                             IF ybox <= SegmentsXYZ.yseg THEN
  155.                                 zbox = (a(m&).z + u) \ SegmentsXYZ.zsegsize
  156.                                 IF zbox >= 0 THEN
  157.                                     IF zbox <= SegmentsXYZ.zseg THEN
  158.                                         IF xbox <> oxseg OR ybox <> oyseg OR zbox <> ozseg THEN
  159.                                             dx% = Counts%(xbox, ybox, zbox)
  160.                                             NspaceObjects(xbox, ybox, zbox, dx%) = m&
  161.                                             Counts%(xbox, ybox, zbox) = dx% + 1
  162.                                         END IF
  163.                                     END IF
  164.                                 END IF
  165.                             END IF
  166.                         END IF
  167.                     END IF
  168.                 END IF
  169.             NEXT
  170.         END IF
  171.     NEXT
  172.  
  173. FUNCTION SizeOf% (a() AS PointRec)
  174.     SizeOf% = UBOUND(a) - LBOUND(a) + 1
  175.  
  176. FUNCTION Collision% (a AS PointRec, b AS PointRec)
  177.     Collision% = 0
  178.     IF ABS(b.x - a.x) > a.radius + b.radius THEN
  179.         EXIT SUB
  180.     ELSE
  181.         IF ABS(b.y - a.y) > a.radius + b.radius THEN
  182.             EXIT SUB
  183.         ELSE
  184.             IF ABS(b.z - a.z) > a.radius + b.radius THEN
  185.                 EXIT SUB
  186.             ELSE
  187.                 Collision% = -1
  188.             END IF
  189.         END IF
  190.     END IF
  191.  
« Last Edit: March 28, 2019, 08:06:57 pm by codeguy »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Ellastic Collisions
« Reply #2 on: March 28, 2019, 08:07:15 pm »
When calculating velocities the trick is NOT to use the New Velocity Value for the 2nd Velocity calculation.

Best to save both old values in variables and use them to calculate the new values.

I fixed your code thus:
Code: QB64: [Select]
  1. _TITLE "Elastic Collisions"   'mod B+ 2019-03-28
  2. ' https://en.wikipedia.org/wiki/Elastic_collision
  3.  
  4. SCREEN _NEWIMAGE(400, 400, 32)
  5.  
  6. TYPE newBlock
  7.     xPos AS SINGLE
  8.  
  9.     vel AS SINGLE
  10.     mass AS INTEGER
  11.  
  12. DIM SHARED Block1 AS newBlock
  13. DIM SHARED Block2 AS newBlock
  14.  
  15. Example
  16.  
  17. 'only need 1 function but know which velocity is which my Mass and Velocity or the other Block's Mass and Velocity
  18. FUNCTION MyVelocity (myM, myV, otherM, otherV)
  19.     sum = myM + otherM
  20.     MyVelocity = myV * (myM - otherM) / sum + otherV * 2 * otherM / sum
  21.  
  22. SUB Example
  23.     ' Elastic collision of unequal masses
  24.     Block1.xPos = 4
  25.     Block1.width = 32
  26.     Block1.vel = 1
  27.     Block1.mass = 1
  28.  
  29.     Block2.xPos = _WIDTH - 20
  30.     Block2.width = 32
  31.     Block2.vel = -1
  32.     Block2.mass = 1
  33.  
  34.     DO
  35.         _LIMIT 60
  36.  
  37.         LINE (0, 0)-(_WIDTH - 1, _HEIGHT - 1), _RGB(127, 127, 127), BF
  38.         LINE (Block1.xPos, _HEIGHT - 20)-(Block1.xPos + Block1.width, _HEIGHT - 4), _RGB(0, 0, 0), BF
  39.         LINE (Block2.xPos, _HEIGHT - 20)-(Block2.xPos + Block2.width, _HEIGHT - 4), _RGB(0, 0, 255), BF
  40.         _DISPLAY
  41.  
  42.         Block1.xPos = Block1.xPos + Block1.vel
  43.         Block2.xPos = Block2.xPos + Block2.vel
  44.  
  45.         IF Block1.xPos + Block1.width >= Block2.xPos THEN
  46.             b1v = Block1.vel: b2v = Block2.vel '<<<<   these get changed so save old values in separate variables
  47.             Block1.vel = MyVelocity(Block1.mass, b1v, Block2.mass, b2v)
  48.             Block2.vel = MyVelocity(Block2.mass, b2v, Block1.mass, b1v)
  49.         END IF
  50.     LOOP UNTIL Done
  51.  
  52.  

Currently set so both blocks bounce away at equal pace.

Oh also better to use SINGLE or DOUBLE for Velocities and probably X positions as well.
« Last Edit: March 28, 2019, 08:33:04 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Ellastic Collisions
« Reply #3 on: March 28, 2019, 08:46:54 pm »
Hey guys
you're wonderful!
While I attempt to understand the problem  you write
and now that I'm going to write my answer I find the question solved!
1. in TYPE the velocity is an INTEGER while the formula gives back a SINGLE
2. velocity2 must get the right initial value of block1.vel to get the right answer
3. you must reset to false the state of collision of the two blocks

here your code modded for output to screen and with values for masses and velocities taken from the example of wikipage that you have posted
Code: QB64: [Select]
  1. _TITLE "Elastic Collisions"
  2. ' https://en.wikipedia.org/wiki/Elastic_collision
  3.  
  4. SCREEN _NEWIMAGE(400, 400, 32)
  5.  
  6. TYPE newBlock
  7.     xPos AS INTEGER
  8.  
  9.     vel AS SINGLE ' AS INTEGER
  10.     mass AS SINGLE ' AS INTEGER
  11.  
  12. DIM SHARED Block1 AS newBlock
  13. DIM SHARED Block2 AS newBlock
  14.  
  15. Example
  16.  
  17. FUNCTION Velocity1 (m1, m2, u1, u2)
  18.     sum = m1 + m2: a = m1 - m2: b = 2 * m2
  19.     Velocity1 = ((a / sum) * u1 + (b / sum) * u2)
  20.  
  21. FUNCTION Velocity2 (m1, m2, u1, u2)
  22.     sum = m1 + m2: a = 2 * m1: b = m2 - m1
  23.     Velocity2 = ((a / sum) * u1 + (b / sum) * u2)
  24.  
  25. SUB Example
  26.     ' Elastic collision of unequal masses
  27.     Block1.xPos = 4
  28.     Block1.width = 32
  29.     Block1.vel = 4 ' 1
  30.     Block1.mass = 3 '2
  31.  
  32.     Block2.xPos = _WIDTH - 20
  33.     Block2.width = 32
  34.     Block2.vel = -6 '-1
  35.     Block2.mass = 5 ' 1
  36.     COLOR _RGB(188, 55, 50), _RGB(10, 127, 127) ' to see the text
  37.     DO
  38.         _LIMIT 60
  39.  
  40.         LINE (0, 0)-(_WIDTH - 1, _HEIGHT - 1), _RGB(127, 127, 127), BF
  41.         LINE (Block1.xPos, _HEIGHT - 20)-(Block1.xPos + Block1.width, _HEIGHT - 4), _RGB(0, 0, 0), BF
  42.         LINE (Block2.xPos, _HEIGHT - 20)-(Block2.xPos + Block2.width, _HEIGHT - 4), _RGB(0, 0, 255), BF
  43.         '        _DISPLAY
  44.  
  45.         Block1.xPos = Block1.xPos + Block1.vel
  46.         Block2.xPos = Block2.xPos + Block2.vel
  47.  
  48.  
  49.         IF Block1.xPos + Block1.width >= Block2.xPos THEN
  50.             oldb1vel = Block1.vel ' to hold old original value of velocity of mass1
  51.             Block1.vel = Velocity1(Block1.mass, Block2.mass, Block1.vel, Block2.vel)
  52.             Block2.vel = Velocity2(Block1.mass, Block2.mass, oldb1vel, Block2.vel)
  53.             Block1.xPos = Block2.xPos - (Block1.width + 1) ' reset collision data
  54.             PRINT Block1.vel, Block2.vel: _DISPLAY: SLEEP 2  'output debug
  55.         END IF
  56.         LOCATE 2, 1: PRINT Block1.vel, Block2.vel: ' output debug
  57.         _DISPLAY
  58.         _DELAY .1 ' to show slowly
  59.     LOOP UNTIL Done OR _KEYHIT = (32)  ' to have a long goal... when is Done created in this code?
  60.  
Thanks to read
Programming isn't difficult, only it's  consuming time and coffee