Posts: 1,616
Threads: 157
Joined: Apr 2022
Reputation:
77
Looks more like Gary from Sponge Bob.
Pete
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
(10-20-2022, 02:36 AM)bplus Wrote: Congrats James,
Looks like you've worked it out for yourself.
And dang if I haven't found another AAU (Aliens among us).
Thanks! Now I need to figure out the actual collision part.
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
OK a ball with a heading of ba (Radians or Degrees) moves like this: (ba = ball Angle)
newX = oldX + speed * Cos(ba in Radians = _D2R(ba in degrees))
newY = oldY + speed * Sin(ba in Radians = _D2R(ba in degrees))
or
dx = change in x = Cos(ba in Radians = _D2R(ba in degrees))
dy = change in y = Sin(ba in Radians = _D2R(ba in degrees))
and
newX = oldX + dx
newY = oldY + dy
When ball is a radius away from a rectangular wall it gets reflected off wall such that:
if wall is left side dx = -dx
if wall is right side dx = -dx
if wall is top dy = - dy
if wall is bottom dy = -dy
That's easy to code and why Ping Pong so easy to code.
But you need to update ball heading too, ba = _Atan2(dy,dx), if you use ba for collisions with say other balls.
A little more tricky with _Atan2 that returns an angle in Radians and between -Pi and Pi usually.
b = b + ...
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
Thanks for this info...I was hoping this next part wouldn't be as difficult as the reflection.
I'm going to keep this really simple for now. I'll start with a single angled wall (set by mouse) and then let a ball drop onto it. And see if I can get the collision point worked out at any angle.
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
10-20-2022, 04:37 PM
(This post was last modified: 10-20-2022, 04:39 PM by bplus.)
Here is my circle intersect line segment detector, thanks to james2464 Random Line Segment Container Problem which I had to create to detect when a ball enters a line segment:
Code: (Select All) ' return count of how many points overlap segment
Function lineSegIntersectCircle (x1, y1, x2, y2, cx, cy, r)
' x1, y1 and x2, y2 are end points of line segment
' cx, cy are circle center with radius r
Dim rtn, i
Dim As Double d, dx, dy, x, y
d = Sqr((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
dx = (x2 - x1) / d
dy = (y2 - y1) / d
For i = 0 To d ' this effectively redraws the line point by point without actually drawing it on screen
x = x1 + dx * i
y = y1 + dy * i
If Sqr((x - cx) ^ 2 + (y - cy) ^ 2) <= r Then rtn = rtn + 1
'if this point is in radius range then it is in intersection of circle and line segment
Next
lineSegIntersectCircle = rtn
End Function
b = b + ...
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
I have a line detector worked out using the same vector info from the reflection. There are two detections involved. One is to detect how far the ball is from the side of the line, and the other checks the distance from the end of the line. You can see these lines by holding the mouse button, or just check the collision without any lines.
The side checking method uses the vector dot product, which was a calculation already used to get the reflection angle. If this distance (line N in program notes) is less than the ball radius, there is a collision with the line.
Code: (Select All) 'vector reflection and line detection demo
'james2464
Screen _NewImage(800, 600, 32)
Const PI = 3.141592654#
Dim c(10) As Long
c(0) = _RGB(30, 30, 30)
c(1) = _RGB(255, 255, 255)
c(2) = _RGB(255, 255, 0)
c(3) = _RGB(255, 0, 0)
c(4) = _RGB(0, 255, 0)
c(5) = _RGB(0, 255, 255)
'0,0 origin
xx = 400
yy = 300
na = 45 'wall starting angle (mouse wheel controlled)
flag = 0
message = 0
Do
_Limit 50
Cls
'=====================================================
mouseclick1 = 0
Do While _MouseInput
na = na + _MouseWheel * 5
Loop
mx% = _MouseX
my% = _MouseY
If mx% < xx - 400 Then mx% = xx - 400
If mx% > xx + 400 Then mx% = xx + 400
If my% < yy - 300 Then my% = yy - 300
If my% > yy + 300 Then my% = yy + 300
lc% = _MouseButton(1)
rc% = _MouseButton(2)
If lc% = -1 Then mouseclick1 = 1
If rc% = -1 Then mouseclick2 = 1
x = 0 - xx + mx%
y = yy - my%
'=====================================================
h = _Hypot(-x, y)
'=====================================================
'origin lines
Line (0, yy)-(800, yy), c(0)
Line (xx, 0)-(xx, 600), c(0)
'=====================================================
Circle (xx + x, yy - y), 39, c(2) 'point I
'=====================================================
nx = Cos(na * (PI / 180)) 'normalize wall angle
ny = Sin(na * (PI / 180)) 'normalize wall angle
dx = -x * ny * -1: dy = y * nx: ndp = dx + dy
'dot product V.N - used to find distance of N
'The distance of N is from the point of origin to the middle of line A
'line A is a line from point I to point R (parallel to the angled wall)
ndpx = Sin(na * (PI / 180)) * ndp
ndpy = Cos(na * (PI / 180)) * ndp
'=====================================================
'calculate point R
th1 = _Atan2(-y, x) 'radian value of ball (point I)
th2 = _Atan2(-ndpy, ndpx) 'radian value of line N
thd = th1 - th2 'find difference
th3 = th2 - thd 'subtract difference from line N
rx = Cos(th3) * h: ry = Sin(th3) * h 'point R position - th3 * length of point I to origin
'=====================================================
'angled wall
a = (Sin(na * .017453292)) * 200
b = (Cos(na * .017453292)) * 200
c(9) = c(1)
'find length of line A
segx = Abs(x - rx)
segy = Abs((yy - y) - (yy + ry))
sega = _Hypot(segx, segy)
'find distance from point I to wall endpoints
i2w1x = Abs(x - b)
i2w1y = Abs(a + y)
i2w2x = Abs(x + b)
i2w2y = Abs(y - a)
i2wh1 = _Hypot(i2w1x, i2w1y)
i2wh2 = _Hypot(i2w2x, i2w2y)
If i2wh1 < i2wh2 Then
i2ws = 1: i2w = i2wh1
Else
i2ws = 2: i2w = i2wh2
End If
If sega < 400 Then
If Abs(ndp) <= 40 Then c(9) = c(3) 'if beside the wall, just check length of line N
Else
If i2w <= 40 Then c(9) = c(3) 'if near the end of the wall, check the radius distance to the wall endpoint
End If
'==========================================================================================
Line (xx, yy)-(xx + b, yy + a), c(9) 'angled wall (collision with ball changes colour)
Line (xx, yy)-(xx - b, yy - a), c(9) 'angled wall (collision with ball changes colour)
If mouseclick1 = 1 Then
Line (xx, yy)-(xx + x, yy - y), c(2) 'line from origin to ball (point I)
Line (xx + x, yy - y)-(xx + rx, yy + ry), c(4) 'line A
Line (xx, yy)-(xx + rx, yy + ry), c(3) 'origin to point R
If sega <= 400 Then
Line (xx, yy)-(xx + ndpx, yy - ndpy), c(5) 'line N
End If
If sega > 400 Then
If i2ws = 1 Then
Line (xx + x, yy - y)-(xx + b, yy + a), c(5)
End If
If i2ws = 2 Then
Line (xx + x, yy - y)-(xx - b, yy - a), c(5)
End If
End If
message = 1
End If
If message = 0 Then
Locate 1, 1
Print "Left click to show lines"
Print "Scroll mouse wheel to rotate"
End If
_Display
If mouseclick2 = 1 Then flag = 1
Loop Until flag = 1
Posts: 1,616
Threads: 157
Joined: Apr 2022
Reputation:
77
Looks like a good start of a billiards game. I would assume round on round surface collisions with the balls instead of just a ball into a cushion, would require even more calculations.
Pete
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
10-21-2022, 09:05 PM
Yeah! can't wait to see it applied to your random container.
b = b + ...
Posts: 263
Threads: 14
Joined: Apr 2022
Reputation:
23
Looks like everything needed is there, incoming vector, relfection vector, line detection and edge detection. Nice job.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
Yeah I think the math is there now, but programming is a different story. So far I've failed to get this to work. The bounces sometimes go in the wrong direction, the ball goes through the line sometimes. The problem seems to be that the calculations are sometimes using wrong info, backwards +/- values etc so I'll need to sort all that out. One thing I'll be thrilled to get right is breaking up a frame. Sometimes the ball is moving at say 10 pixels per frame and it could go past the line by 7 pixels for example. I'd like to somehow correctly break that into two parts so that the ball bounces back those 7 pixels in the new direction. If that makes sense.
|