10-24-2022, 04:57 PM
Making some progress. I worked out the line endpoint collisions, and I'm in the process of sorting out the side collisions. Some things don't quite add up. The endpoints work really well - when rotating the line with the mouse wheel, you can kind of make the ball go where you want.
Code: (Select All)
'vector reflection and line detection demo
'james2464
Dim Shared scx, scy As Integer
scx = 800: scy = 600
Screen _NewImage(scx, scy, 32)
Const PI = 3.141592654#
Dim Shared x, y, h, xv, yv, ndpx, ndpy, rx, ry
Dim Shared cpa, cpb, a, b, a2, b2, xx, yy
Dim Shared 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)
c(6) = _RGB(255, 0, 255)
'location of wall center point
xx = 400
yy = 300
na = 45 'wall starting angle (mouse wheel controlled)
wlen = 150 'wall length - each half
ballrad = 40 'ball radius
xv = 1.5 'ball x velocity
yv = -3.5 'ball y velocity
sbx = 200 'starting x position
sby = 200 'starting y position
flag = 0
message = 0
Do
_Limit 50
Cls
'=====================================================
mouseclick1 = 0
_MouseHide
Do While _MouseInput
na = na + _MouseWheel * 2
Loop
mx% = _MouseX
my% = _MouseY
If mx% < 0 Then mx% = 0
If mx% > scx Then mx% = scx
If my% < 0 Then my% = 0
If my% > scy Then my% = scy
lc% = _MouseButton(1)
rc% = _MouseButton(2)
If lc% = -1 Then mouseclick1 = 1
If rc% = -1 Then mouseclick2 = 1
'sbx = mx%: sby = my% 'ball controlled by mouse
sbx = sbx + xv
sby = sby + yv
If sbx > (scx - ballrad) Then
xv = xv * -1
t = sbx - (scx - ballrad)
sbx = sbx - t
End If
If sby > (scy - ballrad) Then
yv = yv * -1
t = sby - (scy - ballrad)
sby = sby - t
End If
If sbx < ballrad Then
xv = xv * -1
t = ballrad - sbx
sbx = sbx + t
End If
If sby < ballrad Then
yv = yv * -1
t = ballrad - sby
sby = sby + t
End If
'=====================================================
'origin lines
'Line (0, yy)-(800, yy), c(0)
'Line (xx, 0)-(xx, 600), c(0)
'=====================================================
Circle (sbx, sby), (ballrad - 1), c(2) 'screen location of ball
x = sbx - xx: y = 0 - sby + yy 'location relative to wall
'Locate 1, 1
'Print na, x, y
h = (_Hypot(-x, y))
'=====================================================
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 collision 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
sidecollisionpoint
'=====================================================
'angled wall
a = (Sin(na * .017453292)) * wlen
b = (Cos(na * .017453292)) * wlen
a2 = a * -1: b2 = b * -1
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 'determine which end the ball is closer to
i2ws = 1: i2w = i2wh1
Else
i2ws = 2: i2w = i2wh2
End If
If sega < (wlen * 2) Then
If Abs(ndp) <= ballrad Then ' ***** collision with side of the line *****
c(9) = c(3) 'if beside the wall, just check length of line N
collisionpointa = (Sin(na * .017453292)) * (sega / 2)
collisionpointb = (Cos(na * .017453292)) * (sega / 2)
If i2ws = 1 Then
cpa = yy + collisionpointa: cpb = xx + collisionpointb
End If
If i2ws = 2 Then
cpa = yy - collisionpointa: cpb = xx - collisionpointb
End If
Locate 3, 1
Print " i2ws"; i2ws
Circle (cpb, cpa), 5, c(4) 'circle the collision point
sidecollisionvector
End If
Else
If i2w <= ballrad Then ' ***** collision with endpoint of the line *****
c(9) = c(3)
If i2ws = 1 Then
cpa = yy - a2: cpb = xx + b
endpointcollision1
End If
If i2ws = 2 Then
cpa = yy - a: cpb = xx + b2
endpointcollision2
End If
Circle (cpb, cpa), 5, c(4) 'circle the collision point
End If
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 'show geometry lines
If sega <= (wlen * 2) Then
Line (cpb, cpa)-(cpb - xv * 80, cpa - yv * 80), c(2) 'collision to point I
'Line (cpb + x, cpa - y)-(cpb + rx, cpa + ry), c(4) 'line A
Line (cpb, cpa)-(cpb + rx, cpa + ry), c(3) 'collision to point R
Line (cpb, cpa)-(cpb + ndpx, cpa - ndpy), c(5) 'line N
End If
If sega > (wlen * 2) Then
If i2ws = 1 Then
Line (xx + x, yy - y)-(xx + b, yy + a), c(6) 'endpoint collision line
End If
If i2ws = 2 Then
Line (xx + x, yy - y)-(xx - b, yy - a), c(6) 'endpoint collision line
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
Sub sidecollisionpoint
'calculate point R
th1 = _Atan2(-y, x) 'radian value of ball (point I)
'th1 = _Atan2(-yv, xv)
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 collision point
End Sub
Sub sidecollisionvector
tx = xv: ty = yv: th = _Hypot(tx, ty)
tx2 = tx / th: ty2 = ty / th
spd = _Hypot(tx, ty) 'speed of existing motion vector
th1 = _Atan2(tx, -ty) 'radian value of motion vector
th2 = _Atan2(-ndpy, ndpx) 'radian value of line N
thd = th1 - th2 'find difference
th3 = th2 - thd 'subtract difference from line N
newxv = Cos(th3): newyv = Sin(th3)
xv = newxv * spd: yv = newyv * spd * -1
End Sub
Sub endpointcollision1
tx = x - b: ty = y - a2: th = _Hypot(tx, ty)
tx2 = tx / th: ty2 = ty / th
txv = Abs(xv): tyv = Abs(yv): spd = _Hypot(txv, tyv)
xv = tx2 * spd: yv = ty2 * spd * -1
End Sub
Sub endpointcollision2
tx = x - b2: ty = y - a: th = _Hypot(tx, ty)
tx2 = tx / th: ty2 = ty / th
txv = Abs(xv): tyv = Abs(yv): spd = _Hypot(txv, tyv)
xv = tx2 * spd: yv = ty2 * spd * -1
End Sub