Comme promis, voici mon tuto sur les bots pixel.
Avertissement : je me suis mis aux bots pixel il y a 2 heures, ce que je vais vous montrer n'est que la base, pour vous inspirer, et vous montrer qu'on n'est pas obligé de faire de l'AutoIt pour faire des bots pixel, parce qu'en plus mon code fonctionnera sur toutes les plateformes
J'ai testé plusieurs bibliothèques (enfin, j'ai essayé, la plupart ne voulaient pas compiler), et la meilleure est sans conteste pyautogui (https://github.com/asweigart/pyautogui, https://pypi.python.org/pypi/PyAutoGUI)).
Ce module est à jour, fonctionne sous Windows, OSX et Linux, il est tenu à jour (mis à jour il y a 2 mois) et en plus, il y a une super documentation : https://pyautogui.readthedocs.org/.
Je vais (tenter de) réaliser devant vos yeux un bot paysan sur la map 4,2 (à Incarnam).
Commençons par mettre la fenêtre dans une position à laquelle on peut retourner (moi je l'ai mise en plein écran).
Ensuite, il faut prendre des repères, donc pouvoir récupérer les positions de la souris.
Pour ce faire, j'ai légèrement modifié le code fourni en exemple :
import pyautogui, sys
from time import sleep
print('Press Ctrl-C to quit.')
try:
while True:
x, y = pyautogui.position()
positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)
print(positionStr, end='')
sleep(.1)
print('\b' * len(positionStr), end='', flush=True)
except KeyboardInterrupt:
print('\n')
(j'ai juste rajouté un sleep sinon le processus prend 100% du processeur, les boucles infinies sont très rapides en Python)
Il vous suffit d'exécuter ce code dans un terminal de petite taille au-dessus de la fenêtre de dofus.
Ensuite, il faut appuyer sur [return] pour que l'affichage passe sur une autre ligne.
Nous allons lancer un combat pour afficher la grille (mode tactique), et prendre les coordonnées du centre de la case en haut à gauche et de celle en bas à droite.
Loading Image
Maintenant on va prendre la différence des deux coordonnées X, la diviser par 13.5 et la même chose avec Y et 19.5. On nomme dx le premier quotient, et dy le second.
Loading Image.
Ainsi, avec un simple calcul, on pourra connaître les coordonnées de n'importe quelle cellule du jeu.
Il suffit alors de récupérer à l'aide des sources du jeu (je ne vous l'expliquerai pas, à vous de chercher) les cellId des ressources que l'on veut récupérer.
Il ne nous manque plus qu'une seule chose : comment savoir quand une ressource est disponible.
Là, cela relève de l'astuce, moi j'ai remarqué que la fenêtre qui s'ouvrait n'était pas la même dans les deux cas : elle est beaucoup plus haute lorsque le blé est disponible
Loading Image
J'ai donc basé mon critère sur le fait qu'un pixel situé dans la zone de la différence entre les deux fenêtres sera sombre si la ressource est disponible. Comme je n'avais pas d'idée sous la main, j'ai donc dit que ses codes RVB devaient être inférieurs à 50.
Et cela donne :
from pyautogui import *
from time import sleep
xhg,yhg = 208,61
dx = 64
dy = 31.95
liste = [163, 177, 178, 187, 190, 200, 201, 205, 206, 229, 242, 243, 304, 318, 332, 351, 352, 366, 379, 380] #cellids du blé en 4,2
def idToPix(id):
y,x = divmod(id,14)
if y%2==1: x+=.5
y/=2
return round(xhg+x*dx),round(yhg+y*dy)
def isFree(i):
x,y = idToPix(i)
moveTo(x,y)
s = screenshot()
pixel = s.getpixel((x+66,y-66))
if (pixel[0]<50) and (pixel[1]<50) and (pixel[2]<50):
return True
return False
def test():
sleep(3)
for i in liste:
if isFree(i):
click()
sleep(15)
Ce code va juste parcourir une fois les ressources de la map 3 secondes après avoir lancé la fonction test().
Bien sûr, il est très approximatif, j'ai eu que 80% du blé de la map, tout est dans le réglage, et je suis presque sûr que le critère qu'on a choisi pour les pixels sombres dépend de la luminosité.
En plus, quand la fonction sera implémentée dans le module, on pourra détecter la fenêtre au lieu de mesurer les positions des cases.
On pourrait faire quelque chose de mieux en repérant de manière beaucoup précise la petite fenêtre qui s'ouvre lorsqu'on passe la souris sur une ressource : il serait assez facile de simplement regarder à la position du bord supérieur de la plus petite des deux fenêtres et de détecter une discontinuité, par exemple, et ce serait vraiment beaucoup fiable.
De plus, on peut compléter la partie pixel par un sniffer, comme expliqué dans mon précédent tutoriel, et ainsi lire le nombre de pods, de kamas, ou la quantité de ressources : [Python3] [OSX] Comment faire un sniffer !