Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
_Hypot() Function
#1
Wiki help: https://qb64phoenix.com/qb64wiki/index.php/HYPOT

What wiki doesn't say is that this function contains a very useful Distance Formula between two points on a 2D plane.

Distance between two points (x1, y1) and (x2, y2) ( a diagram would be helpful here, sorry I am going to attempt in words only).

Distance = SQR((x1 - x2) ^ 2 + (y1 - y2) ^ 2)

(x1 - x2) represents the length of one leg of a right triangle
(y1 - y2) represents the other leg

So by the Pythagorean Theorem the Hypotenuse (length) equals the SQR of the square (^2) of both sides.
ie Distance = _Hypot(x1 - x2), (y1 - y2))

The point is we have a Distance formula built-into the QB64 Functions and don't need to carry a Distance Function from our Toolbox of Subs and Functions.

I bring this up because I am kicking myself for missing it yesterday in the enRitchied Code for Missile Command here:
https://qb64phoenix.com/forum/showthread...8#pid17088

I shoulda, coulda, done it better like this:
Code: (Select All)
Option _Explicit '                          Get into this habit and save yourself grief from Typos

_Title "Missile Command EnRitchied" '    another b+ mod 2023-06-24, replace distance with _Hypot.
'                                  I probably picked up this game at the JB forum some years ago.

'    Get Constants, Shared Variables and Arrays() declared. These Will Start with Capital Letters.
'        Get Main module variables and arrays declared with starting lower case letters for local.
'        This is what Option _Explicit helps, by forcing us to at least declare these before use.
'      While declaring, telling QB64 the Type we want to use, we can also give brief description.


Const ScreenWidth = 800, ScreenHeight = 600 '                    for our custom screen dimensions
Dim As Integer bombX, bombY '                          incoming bomb screen position to shoot down
Dim As Single bombDX, bombDY '                  DX and DY mean change in X position and Y position
Dim As Integer missileX, missileY '                                              missile position
Dim As Single missileDX, missileDY '                            change X and Y of Missile position
Dim As Integer hits, misses '                                                score hits and misses
Dim As Integer mouseDistanceX, mouseDistanceY '      for calculations of missile DX, DY direction
Dim As Single distance '                                                                    ditto
Dim As Integer radius '                                      drawing hits with target like circles
Dim As Integer boolean '                        to shorten the code line with a bunch of OR tests

Screen _NewImage(ScreenWidth, ScreenHeight, 32) ' sets up a graphics screen with custom dimensions
'                                          the 32 is for _RGB32(red, green, blue, alpha) coloring.
'
_ScreenMove 250, 60 '            this centers screen in my laptop, you may need different numbers

InitializeForRound: '                            reset game and start a round with a bomb falling
Cls
bombX = Rnd * ScreenWidth '                                starts bomb somewhere across the screen
bombY = 0 '                                                          starts bomb at top of screen
bombDX = Rnd * 6 - 3 '                                  pick rnd dx = change in x between -3 and 3
bombDY = Rnd * 3 + 3 '                pick rnd dy = change in y between 3 and 6,  > 0 for falling
missileX = ScreenWidth / 2 '                                  missile base at middle across screen
missileY = ScreenHeight - 4 '  missile launch point at missile base is nearly at bottom of screen
missileDX = 0 '                          missile is not moving awaiting mouse click for direction
missileDY = 0 '                                                                              ditto
distance = 0 '                                            distance of mouse click to missile base

Do
    'what's the score?
    _Title "Click mouse to intersect incoming  Hits:" + Str$(hits) + ", misses:" + Str$(misses)
    _PrintString (400, 594), "^" '                                draw missle base = launch point
    While _MouseInput: Wend '                                            poll mouse to get update
    If _MouseButton(1) Then '              the mouse was clicked calc the angle from missile base
        mouseDistanceX = _MouseX - missileX
        mouseDistanceY = _MouseY - missileY
        distance = (mouseDistanceX ^ 2 + mouseDistanceY ^ 2) ^ .5
        missileDX = 5 * mouseDistanceX / distance
        missileDY = 5 * mouseDistanceY / distance
    End If

    missileX = missileX + missileDX '                                      update missile position
    missileY = missileY + missileDY '                                                        ditto
    bombX = bombX + bombDX '                                                  update bomb position
    bombY = bombY + bombDY '                                                                ditto

    '                    I am about to use a boolean variable to shorten a very long IF code line
    '                                boolean is either 0 or -1 when next 2 statements are execued
    '                                            -1/0 or True/False is everything still in screen?
    boolean = missileX < 0 Or missileY < 0 Or bombX < 0 Or bombY < 0
    boolean = boolean Or missileX > ScreenWidth Or bombX > ScreenWidth Or bombY > ScreenHeight
    If boolean Then ' done with this boolean
        '  reuse boolean to shorten another long code line checking if bomb and missile in screen
        boolean = bombY > ScreenHeight Or missileX < 0 Or missileY < 0 Or missileX > ScreenWidth
        If boolean Then misses = misses + 1
        GoTo InitializeForRound
    End If

    '    if the distance between missle and bomb < 20 pixels then the missile got the bomb, a hit
    'If ((missileX - bombX) ^ 2 + (missileY - bombY) ^ 2) ^ .5 < 20 Then '  show a strike as target

    'rewrite the above line using _Hypot() which is hidden distance forumla
    If _Hypot(missileX - bombX, missileY - bombY) < 20 Then


        For radius = 1 To 20 Step 4 '                        draw concetric circles to show strike
            Circle ((missileX + bombX) / 2, (missileY + bombY) / 2), radius
            _Limit 60
        Next
        hits = hits + 1 '                                                    add hit to hits score
        GoTo InitializeForRound
    Else
        PSet (missileX, missileY), &HFFFFFF00 '                            draw your missle yellow
        PSet (bombX, bombY), &HFF0000FF '                                          draw bomb blue
    End If
    _Limit 20
Loop

Update: testing what happens when I edit this post and save.
Update again: lost the nice edge on right side, can I get it back? No I guess not.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#2
Yep, correct. It's the same formula I use in my toolbox:

Code: (Select All)
FUNCTION VectorLength (V AS Type_Vector2)

    '            -->       _______________________
    ' Formula: || V || = \/ V.x * V.x + V.y * V.y

    VectorLength = _HYPOT(V.x, V.y)

END FUNCTION
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#3
I've generally found _HYPOT to be the fastest performer too. It's also easily extended to 3D.

distance! = _HYPOT( _HYPOT( x, y), z)
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#4
(06-24-2023, 07:47 PM)OldMoses Wrote: I've generally found _HYPOT to be the fastest performer too. It's also easily extended to 3D.

distance! = _HYPOT( _HYPOT( x, y), z)
Whoa, mind blown, didn't even think to do that.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#5
OK everyone knows now how to use _Hypot for distance calculation, so your Test is find the other line I coulda used _Hypot in the code presented in the first post.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#6
(06-25-2023, 11:26 PM)bplus Wrote: OK everyone knows now how to use _Hypot for distance calculation, so your Test is find the other line I coulda used _Hypot in the code presented in the first post.
line 48
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#7
(06-25-2023, 11:29 PM)OldMoses Wrote:
(06-25-2023, 11:26 PM)bplus Wrote: OK everyone knows now how to use _Hypot for distance calculation, so your Test is find the other line I coulda used _Hypot in the code presented in the first post.
line 48

Well you aced that test! Smile
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#8
Well darn, _HYPOT is 15 to 16 times faster than using the old SQR based formula.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)