Jump to content

Human-like Mouse Movement


Recommended Posts

Hi. I wanted to share an algorithm I found online that I thought was neat, so I have ported it over from Python to Autoit.

(If I am not quite sure If I can link to external sites on this forum, so if you're interested in the website I have got this math from, feel free to PM me.)

The code makes a cursor move realistically by simulating gravity pulling the cursor to a point and wind making it move unpredictably. The cursor speeds up from far away, slows down as it gets closer, and stops when it's close enough.

Here is what human mouse movement recorded in Gimp looks like :image.png.5b2770fa927d7ee899390c180eed7948.png

And here are some random examples of what the code can produce on default parameters :

image.png.06d0c14e508dd56f9b9907db42ce1fb3.png

The following is the mouse movement function, use it however you will, but please do not discuss game automation in this thread or contact me about anything having to do with such. (this is against forum rules)

Hope someone finds some good use for this. Happy new years.

 

#include <Math.au3>
#include <Array.au3>

MoveMouse(297, 551,1305,341)

Func MoveMouse($start_x, $start_y, $dest_x, $dest_y, $G_0 = 9, $W_0 = 3, $M_0 = 15, $D_0 = 12)
    Local $current_x = $start_x, $current_y = $start_y
    Local $v_x = 0, $v_y = 0, $W_x = 0, $W_y = 0

    While _Dist($dest_x, $dest_y, $start_x, $start_y) >= 1
        Local $dist = _Dist($dest_x, $dest_y, $start_x, $start_y)
   Local $W_mag = Min($W_0, $dist)

        If $dist >= $D_0 Then
            $W_x = $W_x / Sqrt(3) + (2 * Random() - 1) * $W_mag / Sqrt(5)
            $W_y = $W_y / Sqrt(3) + (2 * Random() - 1) * $W_mag / Sqrt(5)
        Else
            $W_x /= Sqrt(3)
            $W_y /= Sqrt(3)

            If $M_0 < 3 Then
                $M_0 = Random() * 3 + 3
            Else
                $M_0 /= Sqrt(5)
            EndIf
        EndIf

        $v_x += $W_x + $G_0 * ($dest_x - $start_x) / $dist
        $v_y += $W_y + $G_0 * ($dest_y - $start_y) / $dist

        Local $v_mag = _Dist(0, 0, $v_x, $v_y)
        If $v_mag > $M_0 Then
            Local $v_clip = $M_0 / 2 + Random() * $M_0 / 2
            $v_x = ($v_x / $v_mag) * $v_clip
            $v_y = ($v_y / $v_mag) * $v_clip
        EndIf

        $start_x += $v_x
        $start_y += $v_y

        Local $move_x = Round($start_x)
        Local $move_y = Round($start_y)

        If $current_x <> $move_x Or $current_y <> $move_y Then
            MouseMove($move_x,$move_y,1)
            ConsoleWrite("Move Mouse to: " & $move_x & ", " & $move_y & @CRLF)
            $current_x = $move_x
            $current_y = $move_y
        EndIf
    WEnd

    Return $current_x & "," & $current_y
EndFunc

; Calculate distance between two points
Func _Dist($x1, $y1, $x2, $y2)
    Return Sqrt(($x2 - $x1) ^ 2 + ($y2 - $y1) ^ 2)
EndFunc


Func Min($a, $b)
    If $a < $b Then
        Return $a
    Else
        Return $b
    EndIf
EndFunc
Edited by TubbyWs
Typos
Link to comment
Share on other sites

That's pretty fun. It ran fine without those includes (Math and Array) in 3.3.16.1.

Here's a little demo that will start Paint (Win10), if it's not already running, and wait a bit for you to click inside of it to start drawing from where you clicked. By checking for Paint to already be running, you can click in a slightly different starting point to draw lines like in your example images to watch the "human" variations.

;*** The usual configurations
Opt("MustDeclareVars", 1) ;require variables to be declared
Opt("WinTitleMatchMode", 1) ;(default) Match the title from the start (case-sensitive)
Opt("MouseCoordMode", 1) ;(default) absolute screen coordinates
Opt("PixelCoordMode", 1) ;(default) absolute screen coordinates

;*** Set up drawing environment in Paint
Local $sWindowTitle = "Untitled - Paint"
If WinExists($sWindowTitle) = False Then Run("C:\Windows\system32\mspaint.exe", @ScriptDir, @SW_MAXIMIZE)
WinWait($sWindowTitle)
WinActivate("Program Manager") ;take the focus away from Paint

;*** Wait some time for you to aim then click where you want to start drawing
If WinWaitActive($sWindowTitle, "", 10) = 0 Then Exit

;*** Figure out the starting and ending points
Local $aiPos = MouseGetPos()
Local $iPixelsAcross = 1000 ;negative moves left
Local $iPixelsDown = -100 ;negative moves upward

;*** Move it, move it
MouseDown("left")
MoveMouse($aiPos[0], $aiPos[1], $aiPos[0] + $iPixelsAcross, $aiPos[1] + $iPixelsDown)
MouseUp("left")

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...