Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Angle Collisions
#51
Looks more like Gary from Sponge Bob.

Pete
Reply
#52
(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.
Reply
#53
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 + ...
Reply
#54
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.
Reply
#55
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 + ...
Reply
#56
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
Reply
#57
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
Reply
#58
Thumbs Up 
Yeah! can't wait to see it applied to your random container.
b = b + ...
Reply
#59
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:
Reply
#60
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.
Reply




Users browsing this thread: 5 Guest(s)