Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Angle Collisions
#41
(10-18-2022, 03:27 PM)bplus Wrote:
(10-18-2022, 03:57 AM)james2464 Wrote: Changed from arrow keys to mouse wheel for rotating the wall


Code: (Select All)
'vector reflection demo
'james2464

Screen _NewImage(800, 600, 32)

Const PI = 3.141592654#

Dim Shared x, y, h, dx, dy, nx, ny, na As Single


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)


'0,0 origin
xx = 400
yy = 300

Line (0, yy)-(800, yy), c(0)
Line (xx, 0)-(xx, 600), c(0)


x = 70: y = 90 'ball position
na = 60 'reflecting surface angle

flag = 0
Do

    _Limit 10
    Cls

    'chip starting pos - using mouse
    mouseclick1 = 0


    Do While _MouseInput
        na = na + _MouseWheel
    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)
    If lc% = -1 Then mouseclick1 = 1

    x = 0 - xx + mx%
    y = yy - my%

    'origin lines
    Line (0, yy)-(800, yy), c(0)
    Line (xx, 0)-(xx, 600), c(0)


    h = _Hypot(-x, y)

    nx = Sin(na * (PI / 180)) 'normalize wall angle
    ny = Cos(na * (PI / 180)) 'normalize wall angle

    dx = -x * nx * -1: dy = y * ny: 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)

    ard = Sqr(h ^ 2 - ndp ^ 2) 'distance from mid point of line A to point R
    w2x = ny * ard: w2y = nx * ard
    u2x = nx * ndp: u2y = ny * ndp
    rx = w2x + u2x: ry = w2y - u2y 'point R
    Circle (xx + rx, yy + ry), 10, c(3) 'point R
    Line (xx, yy)-(xx + rx, yy + ry), c(3) 'line from origin to point R

    'angled wall
    A = (Sin(na * (PI / 180))) * 200
    B = (Cos(na * (PI / 180))) * 200
    Line (xx, yy)-(xx + B, yy + A), c(1)
    Line (xx, yy)-(xx - B, yy - A), c(1)


    Circle (xx + x, yy - y), 10, c(2) 'point I
    Line (xx, yy)-(xx + x, yy - y), c(2)


    Locate 1, 1
    Print "Vector Reflection"
    Print "Use mouse wheel to rotate wall"
    Locate 35, 1
    Print "Wall angle:"; na

    Locate 1, 70
    Print "I ="; x; ","; y;

    Locate 35, 70
    Print "R ="; Int(rx); ","; Int(-ry)



    _Display

Loop Until flag = 1

Nice app, I would have done it this way https://qb64phoenix.com/forum/showthread...74#pid8074

Yes indeed, that is excellent - thank you!
Reply
#42
(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

I took a shot at doing a test bed program that uses the video procedure.

This is what I came up with, that is mostly vector based.

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

DIM AS V2 wall, ball, reflec, orth, tempv
wall.x = -1: wall.y = 2
orth.x = -wall.y: orth.y = wall.x

SCREEN _NEWIMAGE(600, 600, 32) '                                setup screen & display grid
WINDOW (-300, 300)-(300, -300)
DO UNTIL x% > 300
    IF x% = 0 THEN c~& = &HFF00FF00 ELSE c~& = &H7F7F7F7F
    LINE (-300, x%)-(300, x%), c~&
    LINE (-300, -x%)-(300, -x%), c~&
    LINE (x%, 300)-(x%, -300), c~&
    LINE (-x%, 300)-(-x%, -300), c~&
    x% = x% + 50
LOOP

back& = _COPYIMAGE(0)

DO
    WHILE _MOUSEINPUT: WEND '                                   get inputs
    ball.x = PMAP(_MOUSEX, 2): ball.y = PMAP(_MOUSEY, 3)
    IF _KEYDOWN(18432) THEN '                                   up arrow
        d! = _ATAN2(wall.y, wall.x)
        d! = d! + (_PI / 180)
        wall.x = COS(d!): wall.y = SIN(d!)
        orth.x = -wall.y: orth.y = wall.x
    END IF
    IF _KEYDOWN(20480) THEN '                                   down arrow
        d! = _ATAN2(wall.y, wall.x)
        d! = d! - (_PI / 180)
        wall.x = COS(d!): wall.y = SIN(d!)
        orth.x = -wall.y: orth.y = wall.x
    END IF
    CLS
    _PUTIMAGE , back&
    R2_Norm wall, wall, 200 '                                   draw wall legs 200 long
    R2_Norm orth, orth, 50 '                                    draw orthogonals 50 long
    LINE (wall.x, wall.y)-(-wall.x, -wall.y)
    LINE (orth.x, orth.y)-(-orth.x, -orth.y), &HFF0000FF

    CIRCLE (ball.x, ball.y), 30 '                               draw incoming ball & vector
    LINE (ball.x, ball.y)-(0, 0)
    R2_Norm orth, orth, 1 '                                     reset orthogonal to unit length
    R2_Norm tempv, orth, DotP(ball, orth) * 2 '                 get ball projection to orthogonal * 2
    reflec.x = tempv.x - ball.x '                               compute reflection vector
    reflec.y = tempv.y - ball.y

    LINE (0, 0)-(reflec.x, reflec.y), &HFFFF0000 '              move reflection to impact point
    CIRCLE (reflec.x, reflec.y), 30, &HFFFF0000 '               show reflected ball
    _LIMIT 100
    _DISPLAY
LOOP UNTIL _KEYDOWN(27)
_FREEIMAGE back&
END

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

SUB R2_Norm (re AS V2, v AS V2, scalar AS INTEGER)
    x! = v.x: y! = v.y
    m! = _HYPOT(x!, y!)
    IF m! = 0 THEN
        re.x = 0: re.y = 0
    ELSE
        re.x = (x! / m!) * scalar
        re.y = (y! / m!) * scalar
    END IF
END SUB 'R2_Norm
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#43
Thumbs up! Works without a hitch, nice job!
b = b + ...
Reply
#44
Mark, did you ever get your balls ball unstuck? Your ball in the cave routine worked great, but like you stated, it eventually gets stuck, too. I think I ran it 5 or 10 minutes before that happened, and it got stuck in the same place as the pic you posted.

Pete
Reply
#45
(10-18-2022, 08:44 PM)Pete Wrote: Mark, did you ever get your balls ball unstuck? Your ball in the cave routine worked great, but like you stated, it eventually gets stuck, too. I think I ran it 5 or 10 minutes before that happened, and it got stuck in the same place as the pic you posted.

Pete

I have been thinking of a hack for that, eg if x,y in same place for too long to just kick it off the normal angle for the line segment. Maybe if I do a pinball machine app...

BTW this morning I was revisiting my Pool app which does use a ton of vector stuff: https://qb64phoenix.com/forum/showthread...748#pid748
Old Moses got the perfect link for doing serious calculations, the rack breaks pretty darn well.

I know Pete just wants to talk about bplus balls, do you remember my first post in my little corner?
b = b + ...
Reply
#46
Put my SAM routine to work for ya!

Code: (Select All)
z = TIMER
DO
    x = foo: y = foo2

    IF oldx = x AND oldy = y THEN
        IF z < TIMER THEN z = z - 86400 ' midnight adj.
        IF z - TIMER > .2 THEN
            ' MOVE VARMINT!
            z = TIMER
        END IF

        oldx = x: oldy = y
    END IF
LOOP

Pete
Reply
#47
(10-18-2022, 08:20 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

I took a shot at doing a test bed program that uses the video procedure.

This is what I came up with, that is mostly vector based.

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

DIM AS V2 wall, ball, reflec, orth, tempv
wall.x = -1: wall.y = 2
orth.x = -wall.y: orth.y = wall.x

SCREEN _NEWIMAGE(600, 600, 32) '                                setup screen & display grid
WINDOW (-300, 300)-(300, -300)
DO UNTIL x% > 300
    IF x% = 0 THEN c~& = &HFF00FF00 ELSE c~& = &H7F7F7F7F
    LINE (-300, x%)-(300, x%), c~&
    LINE (-300, -x%)-(300, -x%), c~&
    LINE (x%, 300)-(x%, -300), c~&
    LINE (-x%, 300)-(-x%, -300), c~&
    x% = x% + 50
LOOP

back& = _COPYIMAGE(0)

DO
    WHILE _MOUSEINPUT: WEND '                                   get inputs
    ball.x = PMAP(_MOUSEX, 2): ball.y = PMAP(_MOUSEY, 3)
    IF _KEYDOWN(18432) THEN '                                   up arrow
        d! = _ATAN2(wall.y, wall.x)
        d! = d! + (_PI / 180)
        wall.x = COS(d!): wall.y = SIN(d!)
        orth.x = -wall.y: orth.y = wall.x
    END IF
    IF _KEYDOWN(20480) THEN '                                   down arrow
        d! = _ATAN2(wall.y, wall.x)
        d! = d! - (_PI / 180)
        wall.x = COS(d!): wall.y = SIN(d!)
        orth.x = -wall.y: orth.y = wall.x
    END IF
    CLS
    _PUTIMAGE , back&
    R2_Norm wall, wall, 200 '                                   draw wall legs 200 long
    R2_Norm orth, orth, 50 '                                    draw orthogonals 50 long
    LINE (wall.x, wall.y)-(-wall.x, -wall.y)
    LINE (orth.x, orth.y)-(-orth.x, -orth.y), &HFF0000FF

    CIRCLE (ball.x, ball.y), 30 '                               draw incoming ball & vector
    LINE (ball.x, ball.y)-(0, 0)
    R2_Norm orth, orth, 1 '                                     reset orthogonal to unit length
    R2_Norm tempv, orth, DotP(ball, orth) * 2 '                 get ball projection to orthogonal * 2
    reflec.x = tempv.x - ball.x '                               compute reflection vector
    reflec.y = tempv.y - ball.y

    LINE (0, 0)-(reflec.x, reflec.y), &HFFFF0000 '              move reflection to impact point
    CIRCLE (reflec.x, reflec.y), 30, &HFFFF0000 '               show reflected ball
    _LIMIT 100
    _DISPLAY
LOOP UNTIL _KEYDOWN(27)
_FREEIMAGE back&
END

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

SUB R2_Norm (re AS V2, v AS V2, scalar AS INTEGER)
    x! = v.x: y! = v.y
    m! = _HYPOT(x!, y!)
    IF m! = 0 THEN
        re.x = 0: re.y = 0
    ELSE
        re.x = (x! / m!) * scalar
        re.y = (y! / m!) * scalar
    END IF
END SUB 'R2_Norm
Works great!  Thanks for giving this a go.   I'm still trying to figure it out but I think I'll get there.   Right now I'm trying to get the full 360 degree rotation but I did get the reflection to work at least.  Cheers!
Reply
#48
(10-18-2022, 10:47 PM)james2464 Wrote: [quote pid="8096" dateline="1666124430"]
Works great!  Thanks for giving this a go.   I'm still trying to figure it out but I think I'll get there.   Right now I'm trying to get the full 360 degree rotation but I did get the reflection to work at least.  Cheers!

[/quote]

It was giving me a screwy result until I realized that the orthogonal vector had to be a unit length before applying the dot product calculation. After that the diagonal of the parallelogram was the proper length for obtaining the reflecting vector.

I was pleasantly surprised that dot product handles either side of the reflecting wall perfectly and...

it doesn't matter which orthogonal is constructed...

both...
orth.x = -wall.y: orth.y = wall.x

and...
orth.x = wall.y: orth.y = -wall.x 

work exactly the same. I originally thought there would be a difference. I might be starting to get the hang of this stuff.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#49
I finally got it.  Had to make use of _ATAN2 and that made a huge difference.  I didn't know what it meant but it's a great command for this.  Without using degrees it captures the radian value of any x,y position and you can add and subtract these radian values to get a reflection.    That makes this simple.  I threw out most of my code once I got this concept going.

Code: (Select All)
'vector reflection 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
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)
    If lc% = -1 Then mouseclick1 = 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)

    '=====================================================
    'angled wall
    a = (Sin(na * .017453292)) * 200
    b = (Cos(na * .017453292)) * 200
    Line (xx, yy)-(xx + b, yy + a), c(1)
    Line (xx, yy)-(xx - b, yy - a), c(1)

    '=====================================================
    Circle (xx + x, yy - y), 10, c(2) 'point I
    Line (xx, yy)-(xx + x, yy - y), c(2) 'line from origin to 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
    Circle (xx + rx, yy + ry), 10, c(3) 'point R
    Line (xx, yy)-(xx + rx, yy + ry), c(3) 'origin to point R

    _Display

Loop Until flag = 1
Reply
#50
Congrats James,

Looks like you've worked it out for yourself.

And dang if I haven't found another AAU (Aliens among us).
   
b = b + ...
Reply




Users browsing this thread: 5 Guest(s)