He estado probando varias cosas durante un año. Soy un principiante en python. Hice las dos primeras preguntas en el Proyecto Euler.

He probado algunos métodos para intentar simular teclas en los juegos que juego. Puedo hacer esto fácilmente con autohotkey y macro teclados / mouse. Sin embargo, me gustaría lograr esto a través de Python o C.

Supongo que la api win32 se ignora en los videojuegos y necesito simular las pulsaciones de teclas a través de Direct X.

Gracias de antemano. Aquí está mi último intento ... falló.

Tengo que agarrar / cambiar el mango cada vez que ejecuto una nueva instancia del juego.

Mis teclas simuladas funcionarían en el navegador y el bloc de notas, pero no en el juego. Al no funcionar, quiero decir que no hay entrada del usuario.

El siguiente código cambiaría a la ventana pero no simulará una entrada del usuario.

import pywinauto
import time
from pywinauto import application
app = application.Application()
app.connect_(handle = 0x14002a)
dialogs = app.windows_(handle = 0x14002a)
dlg = app.top_window_()
time.sleep(1)
app.MapleStory.TypeKeys("%A")
time.sleep(1)
app.MapleStory.TypeKeys("%A")
time.sleep(1)
app.MapleStory.TypeKeys("%A")
time.sleep(1)
app.MapleStory.TypeKeys("%A")
time.sleep(1)
app.MapleStory.TypeKeys("%A")
time.sleep(1)
app.MapleStory.TypeKeys("%A")
5
NomNomNom 4 sep. 2014 a las 12:27

2 respuestas

La mejor respuesta

Hemos tenido un largo viaje en mi pasado. Aunque tenemos mucho que aprender aquí es lo que descubrimos:

El envío de claves virtuales se ignorará si el juego se ejecuta en DirectX. Utilice sendinput y envíe los scan_codes en su lugar.

# http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

import ctypes
import time

SendInput = ctypes.windll.user32.SendInput

W = 0x11
A = 0x1E
S = 0x1F
D = 0x20
Z = 0x2C
UP = 0xC8
DOWN = 0xD0
LEFT = 0xCB
RIGHT = 0xCD
ENTER = 0x1C 

# C struct redefinitions 
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time",ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]

# Actuals Functions

def pressKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def releaseKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008 | 0x0002, 0, 
ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

if __name__ == '__main__':
    pressKey(0x11)
    time.sleep(1)
    releaseKey(0x11)
    time.sleep(1)

Fuente: Simula pulsaciones de teclas de Python para controlar un juego http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

Gracias Sentdex por los increíbles tutoriales sobre Machine Learning. He estado queriendo hacer esto en algunos de mis juegos favoritos, pero no pude obtener las claves (debido a DirectX).

Siguiente paso: Kit de controladores de Windows para emular pulsaciones de teclas ...

1
Community 23 may. 2017 a las 12:17

No sé si es demasiado tarde, pero sí, en algunos juegos puedes simular eventos de mouse / teclado usando códigos de escaneo en lugar de teclas virtuales con SendInput

Sin embargo, en cuanto a Maplestory específicamente, no responde tanto a las teclas virtuales como a los códigos de escaneo.

La única forma posible de simular eventos de teclado dentro de este juego que conozco es usar controladores de kernel. Un ejemplo es usar WinIo para escribir directamente en los controladores i8042 e i8048. El comando 0xD2 en 8042 se usa específicamente para simular entradas de nivel de hardware. Sin embargo, WinIo abre un gran agujero de seguridad al exponer los puertos de hardware directamente a los programas espaciales de usuario, por lo que no podría decir que lo recomiendo.

1
Shawn Li 14 oct. 2018 a las 21:45