Angle Collisions
#11
(10-16-2022, 12:17 AM)james2464 Wrote: This video explains the reflection of a vector, but I don't know what 'n' is.  At 10:27 he says "don't forget if n is unit length you know that n.n is 1 and you can cross that out".  But there are still more n's in the formula and I can't figure out what they are supposed to represent.  He just said n=1 !!  Or n.n = 1 anyway.    I just wish there were numbers involved instead of just letters.  That would be a huge help.

https://youtu.be/naaeH1qbjdQ

It can be very confusing mixing vector math and scalar math in the same equation. The former is treating each component (x & y) of the vector with scalar values. Dot product is giving a scalar value, not a vector, but you are then using that scalar to multiply the separate components of vectors. I find it helpful to define a UDT that holds the vector components and relegate dot product calculations to a function that receives both vectors:

Code: (Select All)
TYPE V2
    x AS INTEGER
    y AS INTEGER
END TYPE

FUNCTION R2_Dot (a AS V2, b AS V2)
    R2_Dot = a.x * b.x + a.y * b.y
END FUNCTION


I believe the "n" is the vector normal of the plane. That is, vector 'n' is orthogonal (or perpendicular) to the plane. If it is a "unit" vector, as he seems to indicate, then its length is = 1. Remember that there are two orthogonals to the plane and I suspect that you would have to obtain both and then dot each with the relative position of the ball, keeping the one that is a positive result.

Now n.n I take to mean getting a dot product of a vector with itself, i.e. we are projecting a vector onto itself which necessarily results in a value of 1. Any number over a denominator of 1 is that number. Remember that the dot product of two vectors returns a scalar number, not a vector. Two vectors going in the same direction result in 1, in opposite directions results in -1 and orthogonal vectors result in 0.

v.n/n.n is simply v.n/1 or v.n. So your denominator is taken care of and you simply have to obtain the scalar value of v.n

Clear as mud, I know, and I hope this is not confusing the issue more. I spent many hours watching Professor Leonard videos to try to wrap my head around vectors, which I use in my space flight program, and I still have a lot to learn. As for matrices, I am as yet still at a loss to use them...
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#12
What confuses me about vectors is that a line or line segment has 2 normal vectors each points 90 degrees off the line in question with 180 degrees difference between them. The length or magnitude of the normal vectors aren't needed nearly as much as the actual angle ie which way the normal vector points. It is from that that the reflective angle is compared to incoming angle.
b = b + ...
Reply
#13
(10-16-2022, 01:27 PM)bplus Wrote: What confuses me about vectors is that a line or line segment has 2 normal vectors each points 90 degrees off the line in question with 180 degrees difference between them. The length or magnitude of the normal vectors aren't needed nearly as much as the actual angle ie which way the normal vector points. It is from that that the reflective angle is compared to incoming angle.

I usually resort to adding the third dimension and apply the right hand rule and a cross product calculation in these cases. It requires that one keep track of the point order of the lines, say, taking the clockwise point components and subtracting the counterclockwise point components from it to get a clockwise pointing line vector with a z of 0. This probably also requires a WINDOW redefinition that tracks with mathematical cartesian coordinates as opposed to general screen coordinates, I haven't played with that approach in screen coordinates yet.

Then cross product that vector<v> with a khat vector<v2> defined as <0, 0, 1> and the result vector<re> should be (if the right hand rule is done properly) a normal to each line in question that always points inward to the ball space. Then just put the x & y of <re> back into a 2D vector (the z will be zero anyway). There's probably an easier way, but I don't know it.

Code: (Select All)
TYPE V3
    x AS INTEGER
    y AS INTEGER
    z AS INTEGER
END TYPE

'Description:
'Obtain cross product vector of vectors v and v2
'Right hand rule v is index, v2 is middle, re is thumb
SUB R3_Cross (re AS V3, v AS V3, v2 AS V3)
    re.x = v.y * v2.z - v.z * v2.y
    re.y = -(v.x * v2.z - v.z * v2.x)
    re.z = v.x * v2.y - v.y * v2.x
END SUB 'R3_Cross
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#14
Aha! The reason I can bounce circles inside regular Polygons of any amount of sides is because no side cuts into another.

For James circle bounce container I need to see if a line Segment intersects a circle ie modify my LineIntersectCircle%() function for line Segments, narrow it down from whole line to just a defined segment.
b = b + ...
Reply
#15
(10-16-2022, 01:14 PM)OldMoses Wrote:
(10-16-2022, 12:17 AM)james2464 Wrote: This video explains the reflection of a vector, but I don't know what 'n' is.  At 10:27 he says "don't forget if n is unit length you know that n.n is 1 and you can cross that out".  But there are still more n's in the formula and I can't figure out what they are supposed to represent.  He just said n=1 !!  Or n.n = 1 anyway.    I just wish there were numbers involved instead of just letters.  That would be a huge help.

https://youtu.be/naaeH1qbjdQ

It can be very confusing mixing vector math and scalar math in the same equation. The former is treating each component (x & y) of the vector with scalar values. Dot product is giving a scalar value, not a vector, but you are then using that scalar to multiply the separate components of vectors. I find it helpful to define a UDT that holds the vector components and relegate dot product calculations to a function that receives both vectors:

Code: (Select All)
TYPE V2
    x AS INTEGER
    y AS INTEGER
END TYPE

FUNCTION R2_Dot (a AS V2, b AS V2)
    R2_Dot = a.x * b.x + a.y * b.y
END FUNCTION


I believe the "n" is the vector normal of the plane. That is, vector 'n' is orthogonal (or perpendicular) to the plane. If it is a "unit" vector, as he seems to indicate, then its length is = 1. Remember that there are two orthogonals to the plane and I suspect that you would have to obtain both and then dot each with the relative position of the ball, keeping the one that is a positive result.

Now n.n I take to mean getting a dot product of a vector with itself, i.e. we are projecting a vector onto itself which necessarily results in a value of 1. Any number over a denominator of 1 is that number. Remember that the dot product of two vectors returns a scalar number, not a vector. Two vectors going in the same direction result in 1, in opposite directions results in -1 and orthogonal vectors result in 0.

v.n/n.n is simply v.n/1 or v.n. So your denominator is taken care of and you simply have to obtain the scalar value of v.n

Clear as mud, I know, and I hope this is not confusing the issue more. I spent many hours watching Professor Leonard videos to try to wrap my head around vectors, which I use in my space flight program, and I still have a lot to learn. As for matrices, I am as yet still at a loss to use them...

Thanks for the explanation.   I couldn't understand why a formula meant to reflect a vector would basically destroy the direction info by converting it into a scalar value.   At this point I still don't know what to do with the scalar result, when I'm trying to get a new vector.   

I decided to draw an example to scale.   I'm working on this exact scenario, reflecting a ball off a 75 degree wall.   The ball has a (QB64 screen) vector of (-2,5).   Cartesian (-2,-5).  
I used Mastercam to draw to scale and used that info to create this.   I'm still unable to use the dot product formula to find the R vector.   Hopefully later today I'll have it sorted out.
Code: (Select All)
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)



Line (0, 300)-(800, 300), c(0)
Line (400, 0)-(400, 600), c(0)

A = 200
B = (Cos(75 * (PI / 180))) * A
Line (400 - B, 300 - A)-(400 + B, 300 + A), c(1)


Circle (480, 100), 10, c(2)
A = 200
B = (Tan(21.80140949 * (PI / 180))) * A
Line (400 + B, 300 - A)-(400, 300), c(2)

A = 33.39745962
B = (Tan(75 * (PI / 180))) * A
Line (400 + B, 300 - A)-(400, 300), c(1)

Circle (400 + 169.2820323, 300 + 133.2050808), 10, c(2)
A = 133.2050808
B = (Tan(128.1985905 * (PI / 180))) * A
Line (400 - B, 300 + A)-(400, 300), c(2)


Line (480, 100)-(400 + 169.2820323, 300 + 133.2050808), c(2)

Locate 1, 1
Print "DOT PRODUCT HELL"

Locate 5, 40
Print "75 DEG SURFACE"

Locate 6, 63
Print "I (-2,5)"

Locate 29, 74
Print "R (?,?)"
Reply
#16
Well I could goof up the 4 corners of container and it works showing arrowed directions (but not magnitudes).
Code: (Select All)
_Title "James Random Container" ' b+ 2022-10-16
Screen _NewImage(800, 600, 32)
_ScreenMove 250, 50
Randomize Timer
_PrintMode _KeepBackground
Type lineSegment
    As Single x1, y1, x2, y2, dN ' 2 end points
End Type

' mod RegularPoly to save lines created by
Dim cx, cy, x1, y1, x2, y2 ' building container
Dim As _Unsigned Long PK
Dim As Long NLines, L, Container
ReDim Boundaries(1 To 100) As lineSegment
cx = _Width / 2: cy = _Height / 2 + 40
PK = _RGB32(0, 150, 85) ' minty green background out of bounds
Cls
x1 = 10
y1 = 100
flag = 0
While flag = 0 ' across top of screen left to right
    x2 = (Rnd * 80) + 800 + x1
    If x2 > 750 Then
        x2 = 750
        flag = 1
    End If
    y2 = Rnd * 160 + 50
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0 ' down right side
    y2 = (Rnd * 80) + 600 + y1
    If y2 > 550 Then
        y2 = 550
        flag = 1
    End If
    x2 = 750 - (Rnd * 160 + 50)
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0 ' across bottom right to left
    x2 = x1 - ((Rnd * 80) + 800)
    If x2 < 50 Then
        x2 = 50
        flag = 1
    End If
    y2 = 550 - (Rnd * 60 + 20)
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0
    y2 = y1 - ((Rnd * 80) + 700)
    If y2 < 50 Then
        y2 = 100
        flag = 1
    End If
    x2 = Rnd * 60 + 20
    If flag = 1 Then x2 = 10
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend
Paint (1, 1), PK, PK
Print "  Yellow = the vector of ball heading towards line."
Print "  Blue = vector perpendicular (normal) to boundary line."
Print "  White = angle of refelection off line."
Print "    esc starts a different poly."
Container = _NewImage(_Width, _Height, 32)
_PutImage , 0, Container

Dim bx, by, ba, br, bspeed, hit, hitx1, hity1, hitx2, hity2, diff
bx = cx: by = cy: bspeed = 5
br = 10 ' make ball radius (br) at least 2* speed
ba = Rnd * 360 ' setup up ball in middle of screen/container random heading = ba (ball angle)

' ok just bounce ball around the polygon container
Do
    _PutImage , Container, 0
    Circle (bx, by), br ' draw ball then calc next loaction
    bx = bx + bspeed * CosD(ba) ' test x, y is new ball position if dont run into wall
    by = by + bspeed * SinD(ba)
    For L = 1 To NLines ' did we hit any?

        hit = lineIntersectCircle%(Boundaries(L).x1, Boundaries(L).y1, Boundaries(L).x2, Boundaries(L).y2, bx, by, br, hitx1, hity1, hitx2, hity2)

        ' probably should back it up before processing bounce
        If hit Then ' rebound ball
            Circle (bx, by), br
            _Display
            While hit ' back up circle
                bx = bx + CosD(ba - 180)
                by = by + SinD(ba - 180)
                hit = lineIntersectCircle%(Boundaries(L).x1, Boundaries(L).y1, Boundaries(L).x2, Boundaries(L).y2, bx, by, br, hitx1, hity1, hitx2, hity2)
                Circle (bx, by), br
                _Display
            Wend
            _PutImage , Container, 0
            Circle (bx, by), br

            ' Yellow arrow for incoming towards boundary (I reversed the head of arrow to compare to reflection angle)
            ArrowTo bx + 3 * br * CosD(ba + 180), by + 3 * br * SinD(ba + 180), ba, 3 * br, &HFFFFFF00

            ' Blue Vector Perpendicular to plane
            ArrowTo bx, by, Boundaries(L).dN, 5 * br, &HFF0000FF

            ' Reflected ball off line
            diff = Boundaries(L).dN - ba + 180
            ba = Boundaries(L).dN + diff ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new direction
            ArrowTo bx, by, ba, 3 * br, &HFFFFFFFF

            _Display
            _Delay 1
        End If
    Next
    _Display
    _Limit 30
Loop Until _KeyDown(27)

'' return 0 no Intersect, 1 = tangent 1 point touch, 2 = 2 point intersect
'' if intersect returns point or points of intersect ix1, iy1, ix2, iy2
'' intersect points are -999 if non existent ie no intersect or 2nd point when circle is tangent
Function lineIntersectCircle% (lx1, ly1, lx2, ly2, cx, cy, r, ix1, iy1, ix2, iy2)
    Dim m, y0, A, B, C, D, x1, y1, x2, y2, ydist
    'needs    SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
    If lx1 <> lx2 Then
        slopeYintersect lx1, ly1, lx2, ly2, m, y0 ' Y0 otherwise know as y Intersect

        ' https://math.stackexchange.com/questions/228841/how-do-i-calculate-the-intersections-of-a-straight-line-and-a-circle
        A = m ^ 2 + 1
        B = 2 * (m * y0 - m * cy - cx)
        C = cy ^ 2 - r ^ 2 + cx ^ 2 - 2 * y0 * cy + y0 ^ 2
        D = B ^ 2 - 4 * A * C 'telling part of Quadratic formula = 0 then circle is tangent  or > 0 then 2 intersect points
        If D < 0 Then ' no intersection
            ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
        ElseIf D = 0 Then ' one point tangent
            x1 = (-B + Sqr(D)) / (2 * A)
            y1 = m * x1 + y0
            ix1 = x1: iy1 = y1: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
        Else '2 points
            x1 = (-B + Sqr(D)) / (2 * A): y1 = m * x1 + y0
            x2 = (-B - Sqr(D)) / (2 * A): y2 = m * x2 + y0
            ix1 = x1: iy1 = y1: ix2 = x2: iy2 = y2: lineIntersectCircle% = 2
        End If
    Else 'vertical line
        If r = Abs(lx1 - cx) Then ' tangent
            ix1 = lx1: iy1 = cy: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
        ElseIf r < Abs(lx1 - cx) Then 'no intersect
            ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
        Else '2 point intersect
            ydist = Sqr(r ^ 2 - (lx1 - cx) ^ 2)
            ix1 = lx1: iy1 = cy + ydist: ix2 = lx1: iy2 = cy - ydist: lineIntersectCircle% = 2
        End If
    End If
End Function

Sub slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
    slope = (Y2 - Y1) / (X2 - X1)
    Yintercept = slope * (0 - X1) + Y1
End Sub

' use angles in degrees units instead of radians (converted inside sub)
Function CosD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    CosD = Cos(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function SinD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    SinD = Sin(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function DAtan2 (x1, y1, x2, y2) ' The angle in degrees a 2nd point (x2, y2)  makes to a first point (x1, y1)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    ' Delta means change between 1 measure and another for example x2 - x1
    Dim deltaX, deltaY, rtn
    deltaX = x2 - x1
    deltaY = y2 - y1
    '  To find the angle point(x2, y2) makes to (x1, y1) in Degrees
    ' Take DegreeAngle = DAtan2(y2 - y1, x2 - x1)
    rtn = _R2D(_Atan2(deltaY, deltaX))
    If rtn < 0 Then DAtan2 = rtn + 360 Else DAtan2 = rtn
End Function

' use angles in degrees units instead of radians (converted inside sub)
Sub ArrowTo (BaseX As Long, BaseY As Long, dAngle As Double, lngth As Long, colr As _Unsigned Long)
    Dim As Long x1, y1, x2, y2, x3, y3
    Dim As Double rAngle
    rAngle = _D2R(dAngle)
    x1 = BaseX + lngth * Cos(rAngle)
    y1 = BaseY + lngth * Sin(rAngle)
    x2 = BaseX + .8 * lngth * Cos(rAngle - _Pi(.05))
    y2 = BaseY + .8 * lngth * Sin(rAngle - _Pi(.05))
    x3 = BaseX + .8 * lngth * Cos(rAngle + _Pi(.05))
    y3 = BaseY + .8 * lngth * Sin(rAngle + _Pi(.05))
    Line (BaseX, BaseY)-(x1, y1), colr
    Line (x1, y1)-(x2, y2), colr
    Line (x1, y1)-(x3, y3), colr
End Sub

Line segment intersects with circle is harder to get going.
b = b + ...
Reply
#17
(10-16-2022, 07:45 PM)bplus Wrote: Well I could goof up the 4 corners of container and it works showing arrowed directions (but not magnitudes).
Code: (Select All)
_Title "James Random Container" ' b+ 2022-10-16
Screen _NewImage(800, 600, 32)
_ScreenMove 250, 50
Randomize Timer
_PrintMode _KeepBackground
Type lineSegment
    As Single x1, y1, x2, y2, dN ' 2 end points
End Type

' mod RegularPoly to save lines created by
Dim cx, cy, x1, y1, x2, y2 ' building container
Dim As _Unsigned Long PK
Dim As Long NLines, L, Container
ReDim Boundaries(1 To 100) As lineSegment
cx = _Width / 2: cy = _Height / 2 + 40
PK = _RGB32(0, 150, 85) ' minty green background out of bounds
Cls
x1 = 10
y1 = 100
flag = 0
While flag = 0 ' across top of screen left to right
    x2 = (Rnd * 80) + 800 + x1
    If x2 > 750 Then
        x2 = 750
        flag = 1
    End If
    y2 = Rnd * 160 + 50
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0 ' down right side
    y2 = (Rnd * 80) + 600 + y1
    If y2 > 550 Then
        y2 = 550
        flag = 1
    End If
    x2 = 750 - (Rnd * 160 + 50)
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0 ' across bottom right to left
    x2 = x1 - ((Rnd * 80) + 800)
    If x2 < 50 Then
        x2 = 50
        flag = 1
    End If
    y2 = 550 - (Rnd * 60 + 20)
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0
    y2 = y1 - ((Rnd * 80) + 700)
    If y2 < 50 Then
        y2 = 100
        flag = 1
    End If
    x2 = Rnd * 60 + 20
    If flag = 1 Then x2 = 10
    Line (x1, y1)-(x2, y2), PK
    NLines = NLines + 1
    Boundaries(NLines).x1 = x1: Boundaries(NLines).y1 = y1
    Boundaries(NLines).x2 = x2: Boundaries(NLines).y2 = y2
    Boundaries(NLines).dN = DAtan2(x1, y1, x2, y2) + 90 ' the angle x2, y2 is to x1, y1 + 90 points inward
    x1 = x2
    y1 = y2
Wend
Paint (1, 1), PK, PK
Print "  Yellow = the vector of ball heading towards line."
Print "  Blue = vector perpendicular (normal) to boundary line."
Print "  White = angle of refelection off line."
Print "    esc starts a different poly."
Container = _NewImage(_Width, _Height, 32)
_PutImage , 0, Container

Dim bx, by, ba, br, bspeed, hit, hitx1, hity1, hitx2, hity2, diff
bx = cx: by = cy: bspeed = 5
br = 10 ' make ball radius (br) at least 2* speed
ba = Rnd * 360 ' setup up ball in middle of screen/container random heading = ba (ball angle)

' ok just bounce ball around the polygon container
Do
    _PutImage , Container, 0
    Circle (bx, by), br ' draw ball then calc next loaction
    bx = bx + bspeed * CosD(ba) ' test x, y is new ball position if dont run into wall
    by = by + bspeed * SinD(ba)
    For L = 1 To NLines ' did we hit any?

        hit = lineIntersectCircle%(Boundaries(L).x1, Boundaries(L).y1, Boundaries(L).x2, Boundaries(L).y2, bx, by, br, hitx1, hity1, hitx2, hity2)

        ' probably should back it up before processing bounce
        If hit Then ' rebound ball
            Circle (bx, by), br
            _Display
            While hit ' back up circle
                bx = bx + CosD(ba - 180)
                by = by + SinD(ba - 180)
                hit = lineIntersectCircle%(Boundaries(L).x1, Boundaries(L).y1, Boundaries(L).x2, Boundaries(L).y2, bx, by, br, hitx1, hity1, hitx2, hity2)
                Circle (bx, by), br
                _Display
            Wend
            _PutImage , Container, 0
            Circle (bx, by), br

            ' Yellow arrow for incoming towards boundary (I reversed the head of arrow to compare to reflection angle)
            ArrowTo bx + 3 * br * CosD(ba + 180), by + 3 * br * SinD(ba + 180), ba, 3 * br, &HFFFFFF00

            ' Blue Vector Perpendicular to plane
            ArrowTo bx, by, Boundaries(L).dN, 5 * br, &HFF0000FF

            ' Reflected ball off line
            diff = Boundaries(L).dN - ba + 180
            ba = Boundaries(L).dN + diff ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new direction
            ArrowTo bx, by, ba, 3 * br, &HFFFFFFFF

            _Display
            _Delay 1
        End If
    Next
    _Display
    _Limit 30
Loop Until _KeyDown(27)

'' return 0 no Intersect, 1 = tangent 1 point touch, 2 = 2 point intersect
'' if intersect returns point or points of intersect ix1, iy1, ix2, iy2
'' intersect points are -999 if non existent ie no intersect or 2nd point when circle is tangent
Function lineIntersectCircle% (lx1, ly1, lx2, ly2, cx, cy, r, ix1, iy1, ix2, iy2)
    Dim m, y0, A, B, C, D, x1, y1, x2, y2, ydist
    'needs    SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
    If lx1 <> lx2 Then
        slopeYintersect lx1, ly1, lx2, ly2, m, y0 ' Y0 otherwise know as y Intersect

        ' https://math.stackexchange.com/questions/228841/how-do-i-calculate-the-intersections-of-a-straight-line-and-a-circle
        A = m ^ 2 + 1
        B = 2 * (m * y0 - m * cy - cx)
        C = cy ^ 2 - r ^ 2 + cx ^ 2 - 2 * y0 * cy + y0 ^ 2
        D = B ^ 2 - 4 * A * C 'telling part of Quadratic formula = 0 then circle is tangent  or > 0 then 2 intersect points
        If D < 0 Then ' no intersection
            ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
        ElseIf D = 0 Then ' one point tangent
            x1 = (-B + Sqr(D)) / (2 * A)
            y1 = m * x1 + y0
            ix1 = x1: iy1 = y1: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
        Else '2 points
            x1 = (-B + Sqr(D)) / (2 * A): y1 = m * x1 + y0
            x2 = (-B - Sqr(D)) / (2 * A): y2 = m * x2 + y0
            ix1 = x1: iy1 = y1: ix2 = x2: iy2 = y2: lineIntersectCircle% = 2
        End If
    Else 'vertical line
        If r = Abs(lx1 - cx) Then ' tangent
            ix1 = lx1: iy1 = cy: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
        ElseIf r < Abs(lx1 - cx) Then 'no intersect
            ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
        Else '2 point intersect
            ydist = Sqr(r ^ 2 - (lx1 - cx) ^ 2)
            ix1 = lx1: iy1 = cy + ydist: ix2 = lx1: iy2 = cy - ydist: lineIntersectCircle% = 2
        End If
    End If
End Function

Sub slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
    slope = (Y2 - Y1) / (X2 - X1)
    Yintercept = slope * (0 - X1) + Y1
End Sub

' use angles in degrees units instead of radians (converted inside sub)
Function CosD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    CosD = Cos(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function SinD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    SinD = Sin(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function DAtan2 (x1, y1, x2, y2) ' The angle in degrees a 2nd point (x2, y2)  makes to a first point (x1, y1)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    ' Delta means change between 1 measure and another for example x2 - x1
    Dim deltaX, deltaY, rtn
    deltaX = x2 - x1
    deltaY = y2 - y1
    '  To find the angle point(x2, y2) makes to (x1, y1) in Degrees
    ' Take DegreeAngle = DAtan2(y2 - y1, x2 - x1)
    rtn = _R2D(_Atan2(deltaY, deltaX))
    If rtn < 0 Then DAtan2 = rtn + 360 Else DAtan2 = rtn
End Function

' use angles in degrees units instead of radians (converted inside sub)
Sub ArrowTo (BaseX As Long, BaseY As Long, dAngle As Double, lngth As Long, colr As _Unsigned Long)
    Dim As Long x1, y1, x2, y2, x3, y3
    Dim As Double rAngle
    rAngle = _D2R(dAngle)
    x1 = BaseX + lngth * Cos(rAngle)
    y1 = BaseY + lngth * Sin(rAngle)
    x2 = BaseX + .8 * lngth * Cos(rAngle - _Pi(.05))
    y2 = BaseY + .8 * lngth * Sin(rAngle - _Pi(.05))
    x3 = BaseX + .8 * lngth * Cos(rAngle + _Pi(.05))
    y3 = BaseY + .8 * lngth * Sin(rAngle + _Pi(.05))
    Line (BaseX, BaseY)-(x1, y1), colr
    Line (x1, y1)-(x2, y2), colr
    Line (x1, y1)-(x3, y3), colr
End Sub

Line segment intersects with circle is harder to get going.

Excellent, nice to see this working so well!
Reply
#18
how's this working out? Not perfect but getting closer:


EDIT: added a really awkward paddle. WASD 

Code: (Select All)
'caveball 2.2
ms& = _NewImage(800, 600, 32)
border& = _NewImage(800, 600, 32)
Randomize Timer
Dim c1 As Long
Dim klr As _Unsigned Long
Dim empty As _Unsigned Long
Screen border&
c1 = _RGB(255, 255, 255)
x1 = 50
y1 = 50
flag = 0
While flag = 0
    x2 = (Rnd * 80) + 80 + x1
    If x2 > 750 Then
        x2 = 750
        flag = 1
    End If
    y2 = Rnd * 60 + 20
    fatline x1, y1, x2, y2, 2, c1
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0
    y2 = (Rnd * 80) + 80 + y1
    If y2 > 550 Then
        y2 = 550
        flag = 1
    End If
    x2 = 750 - (Rnd * 60 + 20)
    fatline x1, y1, x2, y2, 2, c1
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0
    x2 = x1 - ((Rnd * 80) + 80)
    If x2 < 50 Then
        x2 = 50
        flag = 1
    End If
    y2 = 550 - (Rnd * 60 + 20)
    fatline x1, y1, x2, y2, 2, c1
    x1 = x2
    y1 = y2
Wend

flag = 0
While flag = 0
    y2 = y1 - ((Rnd * 80) + 80)
    If y2 < 50 Then
        y2 = 50
        flag = 1
    End If
    x2 = Rnd * 60 + 20
    If flag = 1 Then x2 = 50
    fatline x1, y1, x2, y2, 2, c1
    x1 = x2
    y1 = y2
Wend

paddlex = 100
paddley = 100
pang = 0
px2 = paddlex + 10 * Cos(0.01745329 * pang)
py2 = paddley + 10 * Cos(0.01745329 * pang)
bx = 400
by = 400
speed = 2
bang = Int(Rnd * 360)
Screen ms&


Do
    _Limit 60
    Cls
    _PutImage , border&, ms&
    px1 = paddlex - 30 * Cos(0.01745329 * pang)
    py1 = paddley - 30 * Sin(0.01745329 * pang)

    px2 = paddlex + 30 * Cos(0.01745329 * pang)
    py2 = paddley + 30 * Sin(0.01745329 * pang)

    fatline px1, py1, px2, py2, 4, c1
    Select Case kk$
        Case "w"
            paddlex = paddlex + 6 * Cos(0.01745329 * (pang))
            paddley = paddley + 6 * Sin(0.01745329 * (pang))
        Case "s"
            paddlex = paddlex - 6 * Cos(0.01745329 * (pang))
            paddley = paddley - 6 * Sin(0.01745329 * (pang))

        Case "a"
            pang = pang - 5
        Case "d"
            pang = pang + 5
    End Select

    xchange = speed * Cos(0.01745329 * bang)
    ychange = speed * Sin(0.01745329 * bang)
    bm = 0
    For bv = bang - 90 To bang + 90 Step 3
        checkx = bx + (12) * Cos(0.01745329 * bv)
        checky = by + (12) * Sin(0.01745329 * bv)
        klr = Point(checkx, checky)

        If klr = c1 And bm = 0 Then

            xchange = (xchange * -1) * Cos(0.01745329 * (180 - bv))
            ychange = (ychange * -1) * Sin(0.01745329 * (180 - bv))
            bx = bx + xchange
            by = by + ychange
            bang = 180 + bv
            bm = bv
            klr = 0
        End If
    Next
    bx = bx + xchange
    by = by + ychange

    Circle (bx, by), 10, c1
    _Display
    kk$ = InKey$




Loop Until kk$ = Chr$(27)


Sub circleBF (cx As Long, cy As Long, r As Long, klr As _Unsigned Long)
    rsqrd = r * r
    y = -r
    While y <= r
        x = Sqr(rsqrd - y * y)
        Line (cx - x, cy + y)-(cx + x, cy + y), klr, BF
        y = y + 1
    Wend
End Sub

Sub fatline (x0, y0, x1, y1, r, klr As _Unsigned Long)
    If Abs(y1 - y0) < Abs(x1 - x0) Then
        If x0 > x1 Then
            lineLow x1, y1, x0, y0, r, klr

        Else
            lineLow x0, y0, x1, y1, r, klr
        End If
    Else
        If y0 > y1 Then
            lineHigh x1, y1, x0, y0, r, klr
        Else
            lineHigh x0, y0, x1, y1, r, klr
        End If
    End If
End Sub
Sub lineLow (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    yi = 1
    If dy < 0 Then
        yi = -1
        dy = -dy
    End If
    'D = (2 * dy) - dx
    d = (dy + dy) - dx
    y = y0
    For x = x0 To x1
        circleBF x, y, r, klr

        If d > 0 Then
            y = y + yi
            ' D = D + (2 * (dy - dx))
            d = d + ((dy - dx) + (dy - dx))
        Else
            ' D = D + 2 * dy
            d = d + dy + dy
        End If
    Next x
End Sub
Sub lineHigh (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    xi = 1
    If dx < 0 Then
        xi = -1
        dx = -dx
    End If
    ' D = (2 * dx) - dy
    D = (dx + dx) - dy
    x = x0
    For y = y0 To y1
        circleBF x, y, r, klr

        If D > 0 Then
            x = x + xi
            ' D = D + (2 * (dx - dy))
            D = D + ((dx - dy) + (dx - dy))
        Else
            ' D = D + 2 * dx
            D = D + dx + dx
        End If
    Next y
End Sub
Reply
#19
Yeah Point collision detection might work, read around the point of contact enough to get a line angle, figure perpendicular to center, figure the angle incoming and then calculate reflection. Probably more doable than line segment intersection and less a learning curve than vectors.
b = b + ...
Reply
#20
Throwing a second set of detections after the first positive (to each side) and detecting the difference might improve determining how the ball is deflected.
Reply




Users browsing this thread: 18 Guest(s)