Skip to content

Commit

Permalink
Merge pull request #187 from r0ngk/feature
Browse files Browse the repository at this point in the history
Improve handling of mouse speed
  • Loading branch information
steve1316 authored Apr 23, 2023
2 parents 179bc16 + 7f5fdd2 commit ad58a85
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 37 deletions.
23 changes: 23 additions & 0 deletions src-tauri/backend/utils/image_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class ImageUtils:

_reader: easyocr.Reader = None

clickable_area = {
"template_support_summon": (0,-7,420,73),
"ok": (-70,-2,175,32)
}

@staticmethod
def update_window_dimensions(window_left: int, window_top: int, window_width: int, window_height: int, additional_calibration_required: bool = False):
"""Updates the window dimensions for PyAutoGUI to perform faster operations in.
Expand Down Expand Up @@ -851,6 +856,24 @@ def get_button_dimensions(image_name: str) -> Tuple[int, int]:
width, height = image.size
image.close()
return width, height

@staticmethod
def get_clickable_area(image_name: str) -> Tuple[int, int, int, int]:
"""Get the clickable area in /images/buttons/ folder.
Args:
image_name (str): File name of the image in /images/buttons/ folder.
Returns:
(Tuple[int, int]): Tuple of the x-offset, y-offset, width and height.
"""
area = ImageUtils.clickable_area.get(image_name)
if area is not None:
return area

width, height = ImageUtils.get_button_dimensions(image_name)
ImageUtils.clickable_area[image_name] = (0,0,width, height)
return 0,0, width, height

@staticmethod
def _take_screenshot():
Expand Down
55 changes: 32 additions & 23 deletions src-tauri/backend/utils/mouse_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from time import sleep
import numpy as np
import math


class MouseUtils:
Expand All @@ -17,6 +18,10 @@ class MouseUtils:
"""

_hc = pyclick.HumanClicker()
# The lower the more smooth, the higher the more accurate to the speed
mouse_smoothness = max(0.01, Settings.mouse_smoothness/100)
# 1000 to 3000 is tested
mouse_speed = max(1000, 1000 * Settings.custom_mouse_speed)

if Settings.enable_bezier_curve_mouse_movement is False:
pyautogui.MINIMUM_DURATION = 0.1
Expand All @@ -36,11 +41,24 @@ def move_to(x: int, y: int, custom_mouse_speed: float = 0.0):
None
"""
if Settings.enable_bezier_curve_mouse_movement:
# HumanClicker only accepts int as the mouse speed.
if int(custom_mouse_speed) < 1:
custom_mouse_speed = 1

MouseUtils._hc.move((x, y), duration = custom_mouse_speed, humanCurve = pyclick.HumanCurve(pyautogui.position(), (x, y)))
target_pos = (x,y)
pos = pyautogui.position()
# estimate the mouse move distant with euclidean distant of 2 points
dist = [(a - b)**2 for a, b in zip(pos, target_pos)]
dist = math.sqrt(sum(dist))
speed = MouseUtils.mouse_speed-np.random.randint(0,300)
# calculate the duration of the mouse movement
dur = 0.1+dist/speed
target_point_cnt = int(dur/MouseUtils.mouse_smoothness)

if Settings.debug_mode:
MessageLog.print_message(
f"[DEBUG] Duration: {dur}, Number of points: {target_point_cnt})")

curve = pyclick.HumanCurve(pos, target_pos, targetPoints=target_point_cnt)

MouseUtils._hc.move((x, y), duration = dur, humanCurve = curve)
else:
if custom_mouse_speed <= 0.0:
custom_mouse_speed = Settings.custom_mouse_speed
Expand All @@ -50,7 +68,7 @@ def move_to(x: int, y: int, custom_mouse_speed: float = 0.0):
return None

@staticmethod
def move_and_click_point(x: int, y: int, image_name: str, custom_mouse_speed: float = 0.0, mouse_clicks: int = 1):
def move_and_click_point(x: int, y: int, image_name: str, custom_mouse_speed: float = 0.0, mouse_clicks: int = np.random.randint(1,3)):
"""Move the cursor to the specified point on the screen and clicks it.
Args:
Expand All @@ -71,24 +89,13 @@ def move_and_click_point(x: int, y: int, image_name: str, custom_mouse_speed: fl
if Settings.debug_mode:
MessageLog.print_message(f"[DEBUG] New coordinates: ({new_x}, {new_y})")

# Move the mouse to the specified coordinates.
if Settings.enable_bezier_curve_mouse_movement:
# HumanClicker only accepts int as the mouse speed.
if int(custom_mouse_speed) < 1:
custom_mouse_speed = 1

MouseUtils._hc.move((new_x, new_y), duration = custom_mouse_speed, humanCurve = pyclick.HumanCurve(pyautogui.position(), (new_x, new_y)))
else:
if custom_mouse_speed <= 0.0:
custom_mouse_speed = Settings.custom_mouse_speed

pyautogui.moveTo(x, y, duration = custom_mouse_speed, tween = pyautogui.easeInOutQuad)

MouseUtils.move_to(new_x,new_y, custom_mouse_speed=custom_mouse_speed)

pyautogui.mouseDown()
sleep(np.random.uniform(0.02, 0.12))
pyautogui.mouseUp()
for i in range (0, mouse_clicks-1):
sleep(np.random.uniform(0.1,0.2))
sleep(np.random.uniform(0.08,0.16))
pyautogui.mouseDown()
sleep(np.random.uniform(0.02, 0.12))
pyautogui.mouseUp()
Expand All @@ -111,14 +118,16 @@ def _randomize_point(x: int, y: int, image_name: str):
Returns:
(int, int): Tuple of the newly randomized location to click.
"""
from utils.image_utils import ImageUtils
# Get the width and height of the template image.
from utils.image_utils import ImageUtils
width, height = ImageUtils.get_button_dimensions(image_name)

if Settings.farming_mode == "GenericV2":
if Settings.farming_mode.endswith("V2"):
x_off, y_off, width, height = ImageUtils.get_clickable_area(image_name)
width = np.random.randint(0,width)
height = np.random.randint(0,height)
return x+width, y+height
return x+x_off+width, y+y_off+height

width, height = ImageUtils.get_button_dimensions(image_name)

dimensions_x0 = x - (width // 2)
dimensions_x1 = x + (width // 2)
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/backend/utils/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ class Settings:
# #### configuration ####
reduce_delay_seconds: float = dictor(_data, "configuration.reduceDelaySeconds", 0.0)
enable_bezier_curve_mouse_movement: bool = dictor(_data, "configuration.enableBezierCurveMouseMovement", True)
custom_mouse_speed: float = float(dictor(_data, "configuration.mouseSpeed", 0.2))
custom_mouse_speed: float = float(dictor(_data, "configuration.mouseSpeed", 1.5))
mouse_smoothness: float = float(dictor(_data, "configuration.mouseSmoothness", 2))
enable_delay_between_runs: bool = dictor(_data, "configuration.enableDelayBetweenRuns", False)
delay_in_seconds: int = dictor(_data, "configuration.delayBetweenRuns", 15)
enable_randomized_delay_between_runs: bool = dictor(_data, "configuration.enableRandomizedDelayBetweenRuns", False)
Expand Down
4 changes: 3 additions & 1 deletion src/context/BotStateContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface Settings {
reduceDelaySeconds: number
enableBezierCurveMouseMovement: boolean
mouseSpeed: number
mouseSmoothness: number
enableDelayBetweenRuns: boolean
delayBetweenRuns: number
enableRandomizedDelayBetweenRuns: boolean
Expand Down Expand Up @@ -203,7 +204,8 @@ export const defaultSettings: Settings = {
configuration: {
reduceDelaySeconds: 0.0,
enableBezierCurveMouseMovement: true,
mouseSpeed: 0.2,
mouseSpeed: 1.5,
mouseSmoothness: 2,
enableDelayBetweenRuns: false,
delayBetweenRuns: 15,
enableRandomizedDelayBetweenRuns: false,
Expand Down
41 changes: 29 additions & 12 deletions src/pages/ExtraSettings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,25 +195,42 @@ const ExtraSettings = () => {

<Grid.Col span={12}>
<Grid>
<Grid.Col span={6}>
<Grid.Col span={12}>
<CustomSwitch
label="Enable Bezier Curve Mouse Movement"
description="Enable this option to have slow but human-like mouse movement. Disable this for fast but bot-like mouse movement. Note that enabling this will disable the Mouse Speed setting."
checked={bsc.settings.configuration.enableBezierCurveMouseMovement}
onChange={(checked) => bsc.setSettings({ ...bsc.settings, configuration: { ...bsc.settings.configuration, enableBezierCurveMouseMovement: checked } })}
/>
</Grid.Col>
<Grid.Col span={6}>
{!bsc.settings.configuration.enableBezierCurveMouseMovement ? (
<CustomNumberInput
label="Mouse Speed"
value={bsc.settings.configuration.mouseSpeed}
onChange={(value) => bsc.setSettings({ ...bsc.settings, configuration: { ...bsc.settings.configuration, mouseSpeed: value } })}
min={0}
step={0.01}
description="Set how fast a mouse operation finishes."
/>
) : null}

<Grid.Col span={12}>
<Grid align="flex-end">
<Grid.Col span={6}>
<CustomNumberInput
label="Mouse Speed"
value={bsc.settings.configuration.mouseSpeed}
onChange={(value) => bsc.setSettings({ ...bsc.settings, configuration: { ...bsc.settings.configuration, mouseSpeed: value } })}
min={0}
step={0.01}
description="Sets the factor on how fast a mouse operation moves."
/>
</Grid.Col>
<Grid.Col span={6}>
{bsc.settings.configuration.enableBezierCurveMouseMovement ? (
<>
<CustomNumberInput
label="Mouse Smoothness"
value={bsc.settings.configuration.mouseSmoothness}
onChange={(value) => bsc.setSettings({ ...bsc.settings, configuration: { ...bsc.settings.configuration, mouseSmoothness: value } })}
min={0}
step={0.01}
description="Sets the factor on how smooth the mouse movement should be. A lower value has it more smoother (more points along the curve to pass through) and a high value has it move more rigidly (less points along the curve)."
/>
</>
) : null}
</Grid.Col>
</Grid>
</Grid.Col>

<Grid.Col span={6}>
Expand Down

0 comments on commit ad58a85

Please sign in to comment.