peter
peter

Reputation: 4421

python random mouse movements

I would like to make random mouse movements in specified rectangle area (limited with coordinates x1, y1, x2, y2, x3, y3, x4, y4). Movements should be smooth, random, not just straight lines, go randomly up/down/left/right/etc for specified time duration.

Could you give me a hand or working example I can learn from? many thanks

Upvotes: 3

Views: 16410

Answers (5)

Ricardo De Leon
Ricardo De Leon

Reputation: 41

Here is a demo of random X,Y positions you can play as your requirements:

from time import sleep
import pyautogui
import numpy as np

# Check your screen size
print(pyautogui.size())

count=0
while count<1000:
     x=np.random.randint(1,1792)
     y=np.random.randint(1,1120)
     pyautogui.moveTo(x, y)
     print(x)
     print(y)
     sleep(20)
     count+=1

Note: install first

pip3 install pyautogui

Upvotes: 3

newbee
newbee

Reputation: 1

I made this based on Piotr Dabkowski's code, with some extra features (taking random breaks, random scrolls, and users can end early by right clicking). This works for Python 3, and again, for Windows only.

import ctypes
import random
import time
import math
import win32gui

xmax = ctypes.windll.user32.GetSystemMetrics(0) 
ymax = ctypes.windll.user32.GetSystemMetrics(1)

def get_position():
    _, _, (x,y) = win32gui.GetCursorInfo()
    return (x,y)

def move_mouse(pos):
    x_pos, y_pos = pos
    x = int(65536 * x_pos / xmax + 1)
    y = int(65536 * y_pos / ymax + 1)
    return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)

def start(t=30, min_speed=10, max_speed=500, x_bound=[0,xmax], y_bound=[0,ymax],
    p_break = 0.005, break_range = (10, 60), p_scroll = 0.01, scroll_range = (100, 1000)):

    def get_new_speed(min_val, max_val, val, delta=0.01):
        new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
        if new_val<min_val or new_val>max_val:
            return get_new_speed(min_val, max_val, val, delta)
        return new_val

    steps_per_second = 35.0 

    print('Started.')
    endtime = time.time() + int(t*60)

    # Initialize position, speed and direction
    pos = get_position()
    speed = min_speed + random.random()*(max_speed-min_speed)
    direction = 2*math.pi*random.random()
    inside_boundary = False
    right_clicked = False

    # Keep moving mouse until end time, or until right click
    while (not right_clicked) and (time.time() < endtime):
        if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
            right_clicked = True

        time.sleep(1.0/steps_per_second)

        # Taking a break of random duration
        duration = random.randint(*break_range) # in unit of seconds
        break_endtime = time.time() + duration
        r = random.random()
        if (1-p_break) <= r < 1:
            # Keep checking for right click to exit loop
            while (not right_clicked) and (time.time() < break_endtime):
                if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
                    right_clicked = True
                time.sleep(1.0/steps_per_second)
                time_left = break_endtime - time.time()
                print('Paused %d / %ds' % (time_left,duration) + ' '*50, end='\r')
            pos = get_position()
            print(' '*50, end='\r')

        # Random scroll
        r = random.random()
        lines = random.randint(*scroll_range)
        sign = random.random()
        sign = -1 if sign < 0.5 else 1
        if (1-p_scroll) <= r < 1:
            time.sleep(random.random())
            ctypes.windll.user32.mouse_event(2048, 0, 0, sign*lines, 0)
            time.sleep(random.random())
            pos = get_position()

        # Random move
        move_mouse(pos)

        time_left = endtime - time.time()
        print('Running (time left: %ds)' % time_left + ' '*50, end='\r')

        if (pos[0] in range(*x_bound)) and (pos[1] in range(*y_bound)):
            inside_boundary = True

        # Update position, speed and direction
        speed = get_new_speed(min_speed, max_speed, speed)
        direction+=random.randrange(-1,2)*math.pi/5.0*random.random()
        new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
               int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
        # Once mouse position is inside boundary, new position must also be inside
        if inside_boundary:
            while new_pos[0] not in range(*x_bound) or new_pos[1] not in range(*y_bound):
                direction  = 2*math.pi*random.random()
                new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
                   int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
        pos=new_pos
    print('Stopped.' + ' ' * 50)

Upvotes: 0

Piotr Dabkowski
Piotr Dabkowski

Reputation: 5939

This code works on Windows only. You can experiment with the parameters inside the random_movement function to get better results. Good luck!

import ctypes
import random
import time
import math

def move_mouse(pos):
    x_pos, y_pos = pos
    screen_size = ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1)
    x = 65536L * x_pos / screen_size[0] + 1
    y = 65536L * y_pos / screen_size[1] + 1
    return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)

def random_movement(top_left_corner, bottom_right_corner, min_speed=100, max_speed=200):
    '''speed is in pixels per second'''

    x_bound = top_left_corner[0], bottom_right_corner[0]
    y_bound = top_left_corner[1], bottom_right_corner[1]

    pos = (random.randrange(*x_bound),
                    random.randrange(*y_bound))

    speed = min_speed + random.random()*(max_speed-min_speed)
    direction = 2*math.pi*random.random()

    def get_new_val(min_val, max_val, val, delta=0.01):
        new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
        if new_val<min_val or new_val>max_val:
            return get_new_val(min_val, max_val, val, delta)
        return new_val

    steps_per_second = 35.0
    while True:
        move_mouse(pos)
        time.sleep(1.0/steps_per_second) 

        speed = get_new_val(min_speed, max_speed, speed)
        direction+=random.randrange(-1,2)*math.pi/5.0*random.random()

        new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
               int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))

        while new_pos[0] not in xrange(*x_bound) or new_pos[1] not in xrange(*y_bound):
            direction  = 2*math.pi*random.random()
            new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
               int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
        pos=new_pos

Example:

random_movement((300,300),(600,600))

Upvotes: 4

jabaldonedo
jabaldonedo

Reputation: 26582

For performing the movements there is a third-party package call PyUserInput that will allow you to control mouse or keyboard, and it is cross-platform. Install it using pip:

$ pip install PyUserInput

For doing smooth movements you can try what 9000 proposes in his answer.

Upvotes: -1

9000
9000

Reputation: 40894

For random smooth movements constrained to a rectangle I'd try to use Lissajous curves with randomly changing coefficients.

Upvotes: 1

Related Questions