-
Notifications
You must be signed in to change notification settings - Fork 144
Accurately Controlling Your Mouse Pointer
The built-in mouse plugin cannot accurately control the mouse, since it can only control the the "delta", or speed in a specific direction, and Python's execution timing isn't always 100% accurate. Consequently, it also cannot move it to a specific position.
However, this guide will show you how to do just that using the ctypes
Python library.
ctypes
comes with FreePIE, so you don't need to install it separately. It is a library that allows Python to access DLLs and shared libraries, and provides C-compatible data types. You can read more about it on the official Python documentation.
One of the shared libraries accessible from the get-go is User32.dll
. It contains quite a few methods related to UI and UX, one of which allows you to control and read the position of your mouse cursor - SetCursorPos()
and GetCursorPos()
respectively.
SetCursorPos
takes in two values, the target x and y, which correspond to each pixel of your monitor. Make sure the values are plain integers, otherwise the position of the cursor will be massively inaccurate.
All you have to do is import ctypes
. Here is an example script that is meant to control your cell in the popular web game agar.io using a Wiimote and Nunchuck:
import ctypes
# sign - Returns -1 for negatives, 0 for zero and 1 for positives
# val input value
def sign(val):
return (1 * (val > 0)) + (-1 * (val < 0))
# circularArea - maps x and y values into a circular area.
# Mimics how a joystick would work, where the position will return to the center.
# pixelRadius radius of the area in pixels
# origX x value of the origin or center of area
# origY y value of origin of the area
# inX input x value
# inY input y value
def circularArea(pixelRadius, origX, origY, inX, inY):
scaledX = filters.mapRange(-inX, jsRange, -jsRange, -pixelRadius, pixelRadius)
scaledY = filters.mapRange(-inY, jsRange, -jsRange, -pixelRadius, pixelRadius)
posX = origX + scaledX
posY = origY + scaledY
return posX, posY
# dz - establishes a deadzone (probably not necessary)
# val input value
# dz deadzone, everything under it returns a 0
def dz(val, dz):
if abs(val) > dz:
return val
else:
return 0
def update():
# circular range
posX, posY = circularArea(200, scrCenterX, scrCenterY, dz(nchk.stick.x, 2), -dz(nchk.stick.y, 2))
posX = int(posX)
posY = int(posY)
# actual bindings
# only process joystick input when A is pressed down, for safety reasons.
if wiimote[0].buttons.button_down(WiimoteButtons.A):
ctypes.windll.user32.SetCursorPos(posX, posY)
# release mass
keyboard.setKey(Key.W, nchk.buttons.button_down(NunchuckButtons.C))
# split
keyboard.setKey(Key.Space, nchk.buttons.button_down(NunchuckButtons.Z))
# watching values
diagnostics.watch(nchk.stick.x)
diagnostics.watch(nchk.stick.y)
diagnostics.watch(posX)
diagnostics.watch(posY)
if starting:
# joystick variables
jsRange = 100
# screen variables
scrWidth = 1600
scrHeight = 900
scrCenterX = scrWidth / 2
scrCenterY = scrHeight / 2
# aliases
nchk = wiimote[0].nunchuck
nchk.update += update
As shown in the script, make sure you never let the program control your cursor 100% of the time, just to be safe.
HUGE credit to HarvesteR on mtbs3d.com, more specifically this thread (accessed through Web Archive because the site is still down)
Reference
- Reference
-
ahrsimu
device
-
android
device
-
cinemizer
device
-
freeImu
device
-
freespace
device
-
freeTrack
device
-
hydra
device
-
iPad
device
-
iPhone
device
-
iPod
device
-
joystick
device
-
keyboard
device
-
midi
device
-
mouse
device
-
oculusVR
device
-
ppJoy
device
-
speech
device
-
trackIR
device
-
wiimote
device
-
vJoy
device
-
vuzix
device
-
xbox360
device
-
yei
device
-
AxisTypes
Enum
-
Key
Enum
-
MidiStatus
Enum
-
NunchuckButtons
Enum
-
TimingTypes
Enum
-
Units
Enum
-
WiimoteButtons
Enum
-
WiimoteCapabilities
Enum
-
VJoyPov
Enum
-
VuzixDataUnits
Enum
-
diagnostics
Utility
-
filters
Utility
-
freePieIO
Utility
-
system
Utility
Guides and Tips
- freePieIO
- Accurately Controlling Your Mouse Pointer absolute positioning
- Plugin Development