Usage Guide

This guide provides comprehensive examples and explanations for using WindMouse in your projects.

Basic Usage

PyAutoGUI Backend (Cross-Platform)

The PyAutoGUI backend is the recommended choice for cross-platform projects:

from windmouse.pyautogui_controller import PyautoguiMouseController
from windmouse import Coordinate

# Create a controller instance
mouse = PyautoguiMouseController()

# Set the destination coordinates
mouse.dest_position = (Coordinate(800), Coordinate(600))

# Move to the target with default settings
mouse.move_to_target()

AutoHotkey Backend (Windows)

For Windows-specific projects, the AHK backend may provide smoother movements:

from ahk import AHK
from windmouse.ahk_controller import AHKMouseController
from windmouse import Coordinate

# Initialize AHK
ahk = AHK()

# Create a controller instance with AHK
mouse = AHKMouseController(ahk)

# Set destination and move
mouse.dest_position = (Coordinate(1920), Coordinate(1080))
mouse.move_to_target()

Understanding Movement Parameters

The move_to_target() method accepts several parameters that control the movement behavior:

tick_delay

Type: float (default: 0)

Description: Sleep time in seconds between each movement step. Higher values slow down the overall movement.

Use Cases:

  • 0 (default): Maximum speed, no delay

  • 0.001-0.01: Natural speed for most applications

  • 0.05-0.1: Slower, more deliberate movements

Example:

# Fast movement (no delay)
mouse.move_to_target(tick_delay=0)

# Natural speed
mouse.move_to_target(tick_delay=0.005)

# Slow, deliberate movement
mouse.move_to_target(tick_delay=0.1)

step_duration

Type: float (default: 0.1)

Description: Duration in seconds for each individual movement step. This affects the smoothness and speed of the transition between points.

  • Lower values (0.01-0.05): Faster, more abrupt movements

  • Medium values (0.1-0.2): Natural, smooth movements

  • Higher values (0.5-1.0): Very slow, exaggerated movements

Example:

# Quick, snappy movement
mouse.move_to_target(step_duration=0.05)

# Smooth, natural movement (default)
mouse.move_to_target(step_duration=0.1)

# Slow, deliberate movement
mouse.move_to_target(step_duration=0.5)

hold_button

Type: HoldMouseButton (default: HoldMouseButton.NONE)

Description: Specifies which mouse button to hold down during movement, enabling drag-and-drop operations.

Available Options:

  • HoldMouseButton.NONE: No button held (default)

  • HoldMouseButton.LEFT: Hold left mouse button

  • HoldMouseButton.RIGHT: Hold right mouse button

  • HoldMouseButton.MIDDLE: Hold middle mouse button

Example:

from windmouse import HoldMouseButton

# Drag with left mouse button
mouse.dest_position = (Coordinate(500), Coordinate(300))
mouse.move_to_target(hold_button=HoldMouseButton.LEFT)

# Right-click drag
mouse.dest_position = (Coordinate(700), Coordinate(400))
mouse.move_to_target(hold_button=HoldMouseButton.RIGHT)

Fine-Tuning the Physics

The WindMouse algorithm simulates physical forces to create realistic movement. You can customize these parameters when creating the controller.

Understanding the Parameters

gravity_magnitude (default: 9)

Strength of the attractive force pulling the cursor toward the target.

  • Higher values (12-15): More direct paths, faster convergence

  • Lower values (5-7): More curved, wandering paths

wind_magnitude (default: 3)

Amount of random “wind” force creating curvature and unpredictability.

  • Higher values (5-10): More curved, chaotic paths

  • Lower values (1-2): Straighter, more predictable paths

max_step (default: 15)

Maximum velocity/speed of the cursor (measured in pixels per step).

  • Higher values (20-30): Faster overall movement

  • Lower values (5-10): Slower, more controlled movement

damped_distance (default: 12)

Distance from target (in pixels) where the movement begins to slow down and wind effects decrease.

  • Higher values (20-30): Slows down earlier, more cautious approach

  • Lower values (5-10): Maintains speed closer to target

Customization Examples

Aggressive, Fast Movement:

mouse = PyautoguiMouseController(
    gravity_magnitude=15,  # Strong pull toward target
    wind_magnitude=1,      # Minimal curvature
    max_step=25,           # High speed
    damped_distance=8      # Late slowdown
)

Natural, Human-like Movement (Default):

mouse = PyautoguiMouseController(
    gravity_magnitude=9,
    wind_magnitude=3,
    max_step=15,
    damped_distance=12
)

Cautious, Curved Movement:

mouse = PyautoguiMouseController(
    gravity_magnitude=6,   # Weaker attraction
    wind_magnitude=7,      # High curvature
    max_step=10,           # Lower speed
    damped_distance=25     # Early slowdown
)

Drunk/Chaotic Movement (for testing detection):

mouse = PyautoguiMouseController(
    gravity_magnitude=5,
    wind_magnitude=10,
    max_step=8,
    damped_distance=30
)

Advanced Usage Patterns

Setting Start and Destination Separately

You can set start and destination coordinates independently:

mouse = PyautoguiMouseController()

# Set start position explicitly
mouse.start_position = (Coordinate(100), Coordinate(100))

# Set destination
mouse.dest_position = (Coordinate(500), Coordinate(500))

# Or set coordinates individually
mouse.dest_x = Coordinate(800)
mouse.dest_y = Coordinate(600)

mouse.move_to_target()

If you don’t set start_position, the controller automatically uses the current mouse position.

Multiple Sequential Movements

Chain multiple movements together for complex patterns:

from windmouse.pyautogui_controller import PyautoguiMouseController
from windmouse import Coordinate
import time

mouse = PyautoguiMouseController()

# Define a series of waypoints
waypoints = [
    (Coordinate(200), Coordinate(200)),
    (Coordinate(600), Coordinate(200)),
    (Coordinate(600), Coordinate(600)),
    (Coordinate(200), Coordinate(600)),
    (Coordinate(400), Coordinate(400)),  # Return to center
]

# Move through each waypoint
for dest in waypoints:
    mouse.dest_position = dest
    mouse.move_to_target(tick_delay=0.005)
    time.sleep(0.5)  # Pause at each waypoint

Manual Tick-Based Movement

For advanced control, you can manually call tick() instead of move_to_target():

import time

mouse = PyautoguiMouseController()
mouse.dest_position = (Coordinate(800), Coordinate(600))

# Manual control loop
while mouse.tick(step_duration=0.1):
    # Do something between each step
    time.sleep(0.01)

    # You could check conditions and break early
    if some_condition:
        break

This is useful when you need to:

  • Check conditions during movement

  • Synchronize with other operations

  • Implement custom stopping logic

Drag and Drop Operations

Complete drag-and-drop example:

from windmouse.pyautogui_controller import PyautoguiMouseController
from windmouse import Coordinate, HoldMouseButton
import time

mouse = PyautoguiMouseController()

# Move to the item to drag
mouse.dest_position = (Coordinate(300), Coordinate(300))
mouse.move_to_target()
time.sleep(0.2)  # Brief pause

# Drag to destination
mouse.dest_position = (Coordinate(700), Coordinate(500))
mouse.move_to_target(hold_button=HoldMouseButton.LEFT)
time.sleep(0.1)  # Brief pause after drop

Context Manager Pattern

While not built-in, you can create a context manager for cleanup:

from contextlib import contextmanager
from windmouse.pyautogui_controller import PyautoguiMouseController

@contextmanager
def windmouse_controller(**kwargs):
    """Context manager for WindMouse controller."""
    controller = PyautoguiMouseController(**kwargs)
    try:
        yield controller
    finally:
        # Cleanup if needed
        pass

# Usage
with windmouse_controller(gravity_magnitude=10) as mouse:
    mouse.dest_position = (Coordinate(800), Coordinate(600))
    mouse.move_to_target()

Performance Considerations

Movement Speed vs. Realism

There’s a trade-off between speed and realism:

  • Fast movements: Low tick_delay (0-0.001), low step_duration (0.01-0.05)

  • Realistic movements: Medium tick_delay (0.005-0.01), medium step_duration (0.1-0.2)

  • Exaggerated realism: Higher values, more pronounced curves (wind_magnitude 5-10)

Backend Performance

  • PyAutoGUI: Slight overhead from Python → OS calls, but very portable

  • AutoHotkey: Native Windows integration, potentially smoother on Windows systems

For maximum performance:

# Minimal delay configuration
mouse.move_to_target(tick_delay=0, step_duration=0.01)

Screen Resolution Considerations

The WindMouse algorithm scales well across resolutions, but you may want to adjust parameters for different screen sizes:

import pyautogui

# Get screen dimensions
screen_width, screen_height = pyautogui.size()

# Adjust max_step based on screen size
max_step_adjusted = int(screen_width / 100)  # ~19 for 1920px width

mouse = PyautoguiMouseController(max_step=max_step_adjusted)

Best Practices

  1. Always use Coordinate type:

    # Good
    mouse.dest_position = (Coordinate(800), Coordinate(600))
    
    # Avoid (type checker will complain)
    mouse.dest_position = (800, 600)
    
  2. Add small delays between operations:

    import time
    
    mouse.move_to_target()
    time.sleep(0.1)  # Brief pause before next action
    # Click or other operation
    
  3. Test parameter combinations:

    Different applications may be more or less sensitive to mouse patterns. Experiment with physics parameters to find what works best.

  4. Handle exceptions:

    try:
        mouse.dest_position = (Coordinate(800), Coordinate(600))
        mouse.move_to_target()
    except ValueError as e:
        print(f"Invalid coordinates: {e}")
    except Exception as e:
        print(f"Unexpected error: {e}")
    
  5. Consider adding random variations:

    import random
    
    # Add slight randomness to destination
    base_x, base_y = 800, 600
    offset = 5
    dest_x = Coordinate(base_x + random.randint(-offset, offset))
    dest_y = Coordinate(base_y + random.randint(-offset, offset))
    
    mouse.dest_position = (dest_x, dest_y)
    mouse.move_to_target()
    

Common Patterns

Web Scraping

from windmouse.pyautogui_controller import PyautoguiMouseController
from windmouse import Coordinate
import time
import random

def click_element(x: int, y: int):
    """Click an element with natural mouse movement."""
    mouse = PyautoguiMouseController(
        gravity_magnitude=9,
        wind_magnitude=3,
        max_step=12
    )

    # Add slight randomness
    offset = 3
    dest_x = Coordinate(x + random.randint(-offset, offset))
    dest_y = Coordinate(y + random.randint(-offset, offset))

    mouse.dest_position = (dest_x, dest_y)
    mouse.move_to_target(tick_delay=0.003)

    # Small pause before clicking
    time.sleep(random.uniform(0.1, 0.3))

    # Perform click
    import pyautogui
    pyautogui.click()

Game Automation

from windmouse.pyautogui_controller import PyautoguiMouseController
from windmouse import Coordinate
import time

class GameBot:
    def __init__(self):
        self.mouse = PyautoguiMouseController(
            gravity_magnitude=12,  # Faster response
            wind_magnitude=2,      # Less curvature
            max_step=20            # Higher speed
        )

    def target_enemy(self, x: int, y: int):
        """Target and click enemy."""
        self.mouse.dest_position = (Coordinate(x), Coordinate(y))
        self.mouse.move_to_target(
            tick_delay=0,
            step_duration=0.05
        )
        time.sleep(0.05)
        # Perform attack

    def patrol(self, points: list[tuple[int, int]]):
        """Move through patrol points."""
        for x, y in points:
            self.mouse.dest_position = (Coordinate(x), Coordinate(y))
            self.mouse.move_to_target(tick_delay=0.002)
            time.sleep(1.0)  # Wait at each point

Next Steps

  • Learn more about the algorithm internals in Algorithm Explained

  • Explore the complete API reference in API Reference

  • Check out advanced examples in the GitHub repository