_Title "Collision Study #4 press spacebar to toggle tracer" ' b+ 2021-05-09 by bplus ' from "Collision Study #3 Brownian Motion 2018-03-31 by bplus (which was terrible idea of Brownian Motion)
' This time I want to bounce balls with the closest collision first (in case ball is coliidable with 2 or more others)
' PLUS this time I wont change current arrays of ball data but store into NextArray so all bounces are calc'd
' before any new drawing takes place. YES! I think this works better.
' All radii are const for less calc, need balls different colored
Const Xmax
= 600 ' screen width Const Ymax
= 600 ' screen height Const R
= 50 ' balls radii Const Balls
= 18 ' number of balls As Long x
, y
, rr
, gg
, bb
' screen location and RGB colors As Double dx
, dy
' dx, dy = change x, y axis
' these can be static as no balls added or subtracted in closed system
Dim As Ball b
(1 To Balls
), nf
(1 To Balls
) ' b() is current frame balls data , nf( ) is for next frame balls data clrMode = 1
b(i).x = rand(R, Xmax - R)
b(i).y = rand(R, Ymax - R)
b
(i
).dx
= Rnd * 4 + 1 * rdir
b
(i
).dy
= Rnd * 4 + 1 * rdir
b(i).rr = rand%(180, 255)
b(i).gg = rand%(180, 255)
b(i).bb = rand%(180, 255)
For i
= 1 To Balls
' draw balls then update for next frame
Color _RGB32(b
(i
).rr
- rad
/ R
* 150, b
(i
).gg
- rad
/ R
* 150, b
(i
).bb
- rad
/ R
* 150) fcirc b(i).x, b(i).y, rad
' check for collision
cd = 100000: saveJ = 0
For j
= 1 To Balls
'find deepest collision dx = b(i).x - b(j).x: dy = b(i).y - b(j).y
If dx
* dx
+ dy
* dy
< (2 * R
) * (2 * R
) Then ' collision but is it first or deepest collision If R
* R
- dx
* dx
+ dy
* dy
< cd
Then cd
= (2 * R
) * (2 * R
) - dx
* dx
+ dy
* dy: saveJ
= j
If cd
<> 100000 Then ' found collision change ball i dx, dy calc new course for ball i a
= _Atan2(b
(i
).y
- b
(saveJ
).y
, b
(i
).x
- b
(saveJ
).x
) power1 = (b(i).dx ^ 2 + b(i).dy ^ 2) ^ .5
power2 = (b(saveJ).dx ^ 2 + b(saveJ).dy ^ 2) ^ .5
power = (power1 + power2) / 2
nf
(i
).dx
= power
* Cos(a
) nf
(i
).dy
= power
* Sin(a
) nf(i).dx = b(i).dx
nf(i).dy = b(i).dy
'update location of ball next frame
nf(i).x = b(i).x + nf(i).dx
nf(i).y = b(i).y + nf(i).dy
' check in bounds next frame
If nf
(i
).x
< R
Then nf
(i
).dx
= -nf
(i
).dx: nf
(i
).x
= R
If nf
(i
).x
> Xmax
- R
Then nf
(i
).dx
= -nf
(i
).dx: nf
(i
).x
= Xmax
- R
If nf
(i
).y
< R
Then nf
(i
).dy
= -nf
(i
).dy: nf
(i
).y
= R
If nf
(i
).y
> Ymax
- R
Then nf
(i
).dy
= -nf
(i
).dy: nf
(i
).y
= Ymax
- R
'now that we've gone through all old locations update b() with nf() data
b(i).x = nf(i).x: b(i).y = nf(i).y
b(i).dx = nf(i).dx: b(i).dy = nf(i).dy
' next frame ready to draw
rand%
= (Rnd * (hi
- lo
+ 1)) \
1 + lo
'Steve McNeil's copied from his forum note: Radius is too common a name
RadiusError = -subRadius
X = subRadius
Y = 0
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
Line (CX
- X
, CY
)-(CX
+ X
, CY
), , BF
RadiusError = RadiusError + Y * 2 + 1
Line (CX
- Y
, CY
- X
)-(CX
+ Y
, CY
- X
), , BF
Line (CX
- Y
, CY
+ X
)-(CX
+ Y
, CY
+ X
), , BF
X = X - 1
RadiusError = RadiusError - X * 2
Y = Y + 1
Line (CX
- X
, CY
- Y
)-(CX
+ X
, CY
- Y
), , BF
Line (CX
- X
, CY
+ Y
)-(CX
+ X
, CY
+ Y
), , BF