Quand j'ai regardé une vidéo présentant la macro anti-recul d'un certain jeu FPS sur Twitter à la fin de l'année dernière, j'ai pensé qu'un ajustement régulier de la macro serait difficile ~~ C'était proche d'un outil frauduleux, mais en même temps c'était réglé à l'avance. Je me demandais si je pouvais faire quelque chose d'intéressant si je pouvais effectuer les mouvements du jeu.
En Python, il existe des bibliothèques telles que PyAutoGUI et pynput qui font fonctionner la souris et le clavier, et vous pouvez facilement les utiliser et les automatiser en les utilisant. Cependant, le jeu auquel je jouais n'acceptait aucune opération. DirectX est-il impliqué? Après diverses recherches, j'ai trouvé un substitut appelé Serpent.AI qui permet à AI de jouer à des jeux. Serpent.AI semble utiliser le jeu avec l'API Win32, et le jeu auquel je joue pourrait fonctionner avec l'API Win32.
Il existe deux façons d'utiliser la souris avec l'API Win32.
Utilisez les ctypes de bibliothèque standard pour appeler l'API Win32 à partir de Python.
input_1.py
import ctypes
#SetCursorPos(x, y)
ctypes.windll.user32.SetCursorPos(200, 300)
Spécifiez simplement avec x, y (horizontal, vertical). La valeur de (0,0) augmente vers le coin inférieur droit en haut à gauche de l'écran. Ce code déplace le curseur sur x: 200 y: 300. Cependant, SetCursorPos ne peut pas faire fonctionner le jeu.
Vous pouvez déplacer, cliquer et saisir le curseur de la souris. Voir ici pour plus de détails sur son utilisation. Le code est [this](https://github.com/SerpentAI/SerpentAI/blob/b8eec1032c5b1134125fd1124387a3cd9f253d5f/serpent/input_controllers/native_win32_input_controller.py/fr/input_controller.py/serpent/input_controllers/native_win32_input_controller. -union-in-python-to-send-keyboard-events-in-windows) a été utilisé comme référence.
Déclarez la structure INPUT requise pour SendInput et la structure MOUSEINPUT qui contient des informations sur les opérations de la souris.
input_2.py
import ctypes
ULONG_PTR = ctypes.POINTER(ctypes.c_ulong)
#Informations sur les événements de la souris
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", ULONG_PTR)]
class INPUT(ctypes.Structure):
_fields_ = [("type", ctypes.c_ulong),
("mi", MOUSEINPUT)]
Spécifie l'argument SendInput et le type de retour.
input_2.py
LPINPUT = ctypes.POINTER(INPUT)
SendInput = ctypes.windll.user32.SendInput
SendInput.argtypes = (ctypes.c_uint, LPINPUT, ctypes.c_int)
SendInput.restype = ctypes.c_uint
Si vous convertissez les coordonnées et plongez dans SendInput, le curseur de la souris se déplacera.
input_2.py
x, y = 200, 300
x = x * 65536 // 1920
y = y * 65536 // 1080
_mi = MOUSEINPUT(x, y, 0, (0x0001 | 0x8000), 0, None)
SendInput(1, INPUT(0, _mi), ctypes.sizeof(INPUT))
L'explication détaillée sera longue, Dans ces deux lignes, les coordonnées du curseur (200 300) sont converties en coordonnées de 0 à 65 535 (6826,18204). Le diviseur change en fonction de la résolution de l'écran. La division est arrondie vers le bas, mais je m'en fiche car ce n'est pas très différent de l'arrondissement. Comme cela sera décrit plus loin, il n'est nécessaire que pour le mouvement en coordonnées absolues.
input_2.py
x = x * 65536 // 1920 # x * 65536 //Résolution d'écran(côté)
y = y * 65536 // 1080 # y * 65536 //Résolution d'écran(Verticale)
La quantité de rotation de la roue est de 120, ce qui correspond à un cran d'une souris standard. Il n'y a aucun problème avec les entiers autres que les multiples de 120. Vous pouvez également faire défiler horizontalement. Plusieurs événements de souris peuvent être définis avec l'opérateur «|» de l'opérateur bit. J'ai résumé les éléments fréquemment utilisés dans le tableau. Cliquez ici pour plus de détails (https://docs.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-mouseinput)
valeur | sens |
---|---|
0x8000 | Utiliser des coordonnées absolues, des coordonnées relatives si non spécifiées |
0x0001 | Déplacer le curseur |
0x0002 | Appuyez sur le bouton gauche |
0x0004 | Relâchez le bouton gauche |
0x0008 | Appuyez sur le bouton droit |
0x0010 | Relâchez le bouton droit |
0x01000 | Défilement horizontal ou non |
0x0800 | Défilement vertical ou non |
Une chose à noter ici. Le format des coordonnées change selon que vous utilisez des coordonnées absolues ou relatives. Lors de l'utilisation de coordonnées absolues, il est nécessaire de convertir en coordonnées de 0 à 65 535, mais lors de l'utilisation de coordonnées relatives, la conversion des coordonnées n'est pas nécessaire. Dans ce cas, il reste (200 300).
input_2.py
# MOUSEINPUT(coordonnée x,coordonnée y,Quantité de rotation de roue,Événement souris, 0, None)
_mi = MOUSEINPUT(x, y, 0, (0x0001 | 0x8000), 0, None)
Il existe trois types d'entrées, comme indiqué dans le tableau ci-dessous.
valeur | sens |
---|---|
0 | Entrée souris |
1 | La saisie au clavier |
2 | Entrée matérielle |
input_2.py
# SendInput(1, INPUT(Type d'entrée, _mi), ctypes.sizeof(INPUT))
SendInput(1, INPUT(0, _mi), ctypes.sizeof(INPUT))
Dans SendInput, vous pouvez utiliser le clavier en plus du fonctionnement de la souris, mais par souci de simplicité, nous nous sommes concentrés sur le fonctionnement de la souris. La prochaine fois, je vais l'expliquer, y compris le fonctionnement du clavier.
Je ne pense pas que ce soit pertinent pour quiconque lit cet article, mais le programme lui-même a été achevé il y a longtemps. Quand j'écrivais le programme, je ne pensais pas profondément à Yoshi si je déménageais, donc quand je l'ai regardé plus tard, c'était censé être Tondemonai. J'ai mis un commentaire. Alors, tout en organisant, j'ai écrit un article sur les principaux points du programme. Si vous écrivez un article comme celui-ci, vous ne l'oublierez pas.
Recommended Posts