Posts: 276
Threads: 14
Joined: Apr 2022
Reputation:
27
(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:
Posts: 3,932
Threads: 175
Joined: Apr 2022
Reputation:
215
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 + ...
Posts: 276
Threads: 14
Joined: Apr 2022
Reputation:
27
(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:
Posts: 3,932
Threads: 175
Joined: Apr 2022
Reputation:
215
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 + ...
Posts: 229
Threads: 25
Joined: Aug 2022
Reputation:
23
(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 (?,?)"
Posts: 3,932
Threads: 175
Joined: Apr 2022
Reputation:
215
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 + ...
Posts: 229
Threads: 25
Joined: Aug 2022
Reputation:
23
(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!
Posts: 660
Threads: 142
Joined: Apr 2022
Reputation:
58
10-16-2022, 08:07 PM
(This post was last modified: 10-16-2022, 08:43 PM by James D Jarvis.)
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
Posts: 3,932
Threads: 175
Joined: Apr 2022
Reputation:
215
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 + ...
Posts: 660
Threads: 142
Joined: Apr 2022
Reputation:
58
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.
|