Maksiks
Maksiks

Reputation: 116

How do I achieve smooth mouse movement on turns in Pyautogui?

How to achieve smooth mouse movement instead of teleportation between points on turns in pyautogui? How to setup paths for your mouse to move instead of it just teleporting unless you try to manually interpolate it for hours?

Upvotes: 0

Views: 3333

Answers (2)

Maksiks
Maksiks

Reputation: 116

You can't (kind of)

Pyautogui is a library meant for automation and isn't meant to be used for smooth movement, you can consider other libraries for this if you can find one.

Except you can

This is a bit of a workaround

Curves

To achieve proper smooth motion especially with curves we use mathematical functions to determine our path and loops to increment our x cordinate (in my example the x cordinate is "a" and the y cordinate is "b").

Use Desmos, or a different graphical calcualtor for visualizing the graph of the function before making it in code. Might seem like extra effort but this is vital.

Important: the y cordinate is inversed in pyautogui, account for that.

I used "x" and "y" variables as center's of the screen on respective axis but you can start wherever you want by replacing them.

Workaround

Then we set pyautogui.pause to 0 so there's no pause between movements. It's quite frankly broken, duration values above 0.2 yield slow speeds, and <= 0.2 offer very high speed, this is not meant to be used for this but it just works. By setting the duration to 0.2 we can edit our step (the incrementation of the function) to achieve the necessary speed. And it is smooth.

Here's a functional example: it draws an infinity symbol with your mouse. Make sure that you are able to stop it in your IDE, it's ctrl+F2 in Pycharm.

import pyautogui
import time

screenSize = pyautogui.size()

x = screenSize[0]/2
y = screenSize[1]/2

time.sleep(3)

# SETTINGS

pyautogui.PAUSE = 0

# Multiplier
size = 100
# Duration
speed = 0.2
# Incrementation
step = 0.0001

pyautogui.moveTo(x, y, 0)

a = step

loopStart = True

while True:
    if loopStart:
        while True:
            a += step
            b = -(a - 2) * 0.5 - 1

            pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
            if a >= 2:
                break

    while True:
        a += step
        b = (((a - 2) ** 4) * 0.8) - 1

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a >= 3:
            a += step
            break

    while True:
        a -= step
        b = -(((a - 2) ** 4) * 0.8) + 1

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a <= 2:
            a -= step * 2
            break

    while True:
        a -= step
        b = a * 0.5

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a <= -2:
            a += step
            break

    # Side 2

    while True:
        a -= step
        b = (((a + 2) ** 4) * 0.8) - 1

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a <= -3:
            a -= step
            break

    while True:
        a += step
        b = -(((a + 2) ** 4) * 0.8) + 1

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a >= -2:
            a += step*2
            break

    while True:
        a += step
        b = -(a + 2) * 0.5 + 1

        pyautogui.moveTo(x + a * size, y + b * size, speed * 0.5, pyautogui.linear)
        if a >= 2:
            loopStart = False
            break

# I think this is also accomplishable by running code in parallel, but this weird method is better anyway.
# Ideally you want to use a proper library like the currently broken (as of August 2023) Autopy for this.

I know this is a highly requested question but I haven't found a single proper answer which weirded me out a lot and resulted in the creation of this QnA-ish post. Hope someone finds this useful <3

Upvotes: 1

Dwaynediddy
Dwaynediddy

Reputation: 1

You can use duration

    pyautogui.moveTo(x, y, duration=0.3)

Upvotes: 0

Related Questions