AUTOIT VS DEAD PIXEL - MEDALLA DE PLATA PARA AUTOIT (APROXIMADAMENTE ENTRE 9800 Y 9850 PUNTOS DE 10000)
Bueno, más o menos he hecho un código operativo digamos....... al 80%?
. El código funciona casi siempre bien, lo que pasa que tiene algunos fallos que no he investigado (no se muy bien por que pasan), y otros que paso de corregir, ya que tendría que seguir escribiendo más código y calentándome la cabeza........y paso
.
Vamos a ver los fallos raros:
Uno es que a veces pega como un pequeño frenazo que hace que el programa no funcione al 100%. No se si será por algo del gdiplus o del modo que he programado esto
. O porque en ese momento hay muchos colores que analizar y se relentiza el script. Quien sabe.
Otro es que a veces (muy pocas veces) el programa no cliquea el recuadro que debe y falla (le cuesta una vida). Al ocurrir esto puede pasar varias cosas, que se pare totalmente o que no vaya bien a causa de que el contador de niveles se descuadre. Esta última causa no se por que ocurre. Puede que falle por culpa de algún recuadro de los que se mueven y se equivoque. Esto se corregiría tratando mejor el algoritmo de detección de formas.
Y los fallos evitables son:
Como ya dije en el post anterior, tendríamos que tratar los cuadrados que salen pegados a los bordes de una forma distinta, ya que el modo que he ideado no vale. Se podría hacer, pero como he dicho antes, no me apetece meterme más a fondo con el asunto. Si a alguien le interesa le puedo explicar lo que yo haría para solucionar este problema.
No explico lo que hace el programa, ya que está comentado en mi post anterior y también he comentado algo el programa. A quien le interese que lea el post anterior.
Si no entendéis algo preguntar, que si puedo os lo explico.
IMPORTANTE: Este flash inicialmente carga un anuncio. Os lo podéis saltar dando al botón saltar anuncio.
CUANDO APAREZCA LA PANTALLA QUE PONE PLAY EN COLOR BLANCO Y DEAD PIXEL EN AZUL, DARLE AL BOTÓN DE ABAJO QUE PONE "PLAY (JUGAR)". En ese momento el script jugará solo. Veréis que velocidad
.
Código: Seleccionar todo
;Game Bot - Dead Pixel
;http://www.minijuegosgratis.com/flash1234/no_hotlink/deadpixel.swf
#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <IE.au3>
#include <ScreenCapture.au3>
Opt("PixelCoordMode", 0) ;1=absolute, 0=relative, 2=client
Local $colorAnterior=0
Local $oIE = _IECreateEmbedded() ;creo el control insertado IE.
Local $Gui=GUICreate("Juego Dead Pixel", 665, 580, _
(@DesktopWidth - 640) / 2, (@DesktopHeight - 580) / 2, _
$WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS + $WS_CLIPCHILDREN)
GUICtrlCreateObj($oIE, 10, 10, 644, 485) ;creo el control insertado IE.
Local $GUI_Button_Back = GUICtrlCreateButton("PLAY (JUGAR)", 250, 540, 100, 30)
GUISetState() ;Show GUI
_IENavigate($oIE, "http://www.minijuegosgratis.com/flash1234/no_hotlink/deadpixel.swf")
While 1
Local $msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
ExitLoop
Case $msg = $GUI_Button_Back
$hwndJuego=ControlGetHandle($Gui,"","MacromediaFlashPlayerActiveX1") ;obtengo el handle del control flash del juego
_GDIPlus_Startup()
$contador=1 ;contador de los niveles. Hay 100 en total, 50 de cuadrados 16x16 y 50 de 8x8.
$maxLadosIn=15 ;máximo de los lados interiores del cuadrado. Son de 16 pixeles. Van del 0 al 15.
$maxLadosOut=16 ;máximo de los lados exteriores del cuadrado. Es justo cuando empieza el fondo.
;Comprueba dos pixeles, uno perteneciente a la palabra "PLAY" y otro a "DEAD PIXEL".
$play=PixelGetColor(321,240,$hwndJuego)
$DeadPixel=PixelGetColor(290,78,$hwndJuego)
If $play=16711422 And $deadpixel=39578 Then ;si los pixeles son los de la palabra podeis darle al botón "PLAY" y empezar la partida.
ControlClick($Gui,"","MacromediaFlashPlayerActiveX1","left",1,321,240)
Sleep(20)
while 1
$hBitmap=_ScreenCapture_CaptureWnd("",$hwndJuego,0,0,-1,-1,False) ;capturo la imagen del control flash (el juego)
$pBitmap=_GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
;bloqueo los bits con los que voy a trabajar en modo lectura.
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF32RGB)
;cojo datos de la estructura anterior que nos facilitarán el poder trabajar con las posiciones exactas de los píxeles en memoria.
$stride = DllStructGetData($BitmapData, "Stride")
$ptr = DllStructGetData($BitmapData, "Scan0")
;miro cual es el color de fondo.
$struct = DllStructCreate("dword", $ptr + $stride * 50 + 4 * 70) ; 4 bytes BBGGRRXX
$colorFondo = DllStructGetData($struct, 1)
$struct = DllStructCreate("dword", $ptr + $stride * 50 + 4 * 570) ; 4 bytes BBGGRRXX
$colorAux = DllStructGetData($struct, 1)
;~ ConsoleWrite($colorFondo & " " & $colorAux & @CR)
If $colorFondo<>$colorAux Then
$struct = DllStructCreate("dword", $ptr + $stride * 360 + 4 * 70) ; 4 bytes BBGGRRXX
$color = DllStructGetData($struct, 1)
If $color=$colorAux Then
$colorFondo=$color
EndIf
EndIf
;realizo dos bucles que recorren toda la pantalla donde puede estar el cuadrado a encontrar. Salto de 8 en 8 para hacerlo más rápido.
For $x=65 To 574 Step 8;$maxLadosOut
For $y=46 To 363 Step 8;$maxLadosOut
$struct = DllStructCreate("dword", $ptr + $stride * $y + 4 * $x) ; 4 bytes BBGGRRXX
$color = DllStructGetData($struct, 1)
If $color<>$colorFondo Then ;si encuentro un color distinto al color de fondo entro en la condición.
;~ ConsoleWrite($x & "," & $y & " " & $color & @CR)
$x1=$x
Do ;miro cual puede ser el primer pixel en la posición x del cuadrado.
$x1-=1
$struct = DllStructCreate("dword", $ptr + $stride * $y + 4 * $x1) ; 4 bytes BBGGRRXX
$colorCuadrado = DllStructGetData($struct, 1)
Until $colorCuadrado<>$color
$x1+=1
$struct = DllStructCreate("dword", $ptr + $stride * $y + 4 * ($x1+$maxLadosIn)) ; 4 bytes BBGGRRXX
$colorCuadrado = DllStructGetData($struct, 1)
;~ MsgBox(0,"",$colorCuadrado2=$colorCuadrado)
If $colorCuadrado=$color Then
$y1=$y
Do ;miro cual puede ser el primer pixel en la posición y del cuadrado.
$y1-=1
$struct = DllStructCreate("dword", $ptr + $stride * $y1 + 4 * $x) ; 4 bytes BBGGRRXX
$colorCuadrado = DllStructGetData($struct, 1)
Until $colorCuadrado<>$color
$y1+=1
$clickCuadrado=True
;~ ConsoleWrite($colorCuadrado &","&$color&@cr)
;compruebo los cuadrados vecinos (las cuatro esquinas) para ver si tienen el mismo color que el encontrado, y así puede que sea ese el cuadrado.
For $n1=0 To $maxLadosIn Step $maxLadosIn
For $n2=0 To $maxLadosIn Step $maxLadosIn
$struct = DllStructCreate("dword", $ptr + $stride * ($y1+$n2) + 4 * ($x1+$n1)) ; 4 bytes BBGGRRXX
$colorCuadrado = DllStructGetData($struct, 1)
;~ ConsoleWrite("lados"&@cr)
If $colorCuadrado<>$color Then
;~ ConsoleWrite($color&@cr)
$clickCuadrado=False
ExitLoop(2)
EndIf
Next
Next
;me aseguro que es un cuadrado con la medida exacta mirando los pixeles exteriores (justos los fronterizos)
If $clickCuadrado Then
For $n2=-1 To $maxLadosOut Step $maxLadosOut+1
$struct = DllStructCreate("dword", $ptr + $stride * ($y1+$n2) + 4 * ($x1+$maxLadosOut)) ; 4 bytes BBGGRRXX
$colorCuadrado = DllStructGetData($struct, 1) ;color
If $colorCuadrado<>$colorFondo Then
$clickCuadrado=False
ExitLoop(2)
EndIf
Next
If $clickCuadrado Then ;si se ha encontrado el cuadrado, cliqueo la posición inicial encontrada (x1,y1) más 4.
$contador+=1
ControlClick($Gui,"","MacromediaFlashPlayerActiveX1","left",1,$x1+4,$y1+4)
If $contador=50 Then ;si el contador llega a 50 (nivel 50) cambio los valores para trabajar con los cuadrados de tamaño 8x8.
ConsoleWrite(">>50"&@cr)
$maxLadosIn=7
$maxLadosOut=8
ElseIf $contador=100 Then ;Si llega al nivel 100 paro de buscar cuadrados.
ConsoleWrite(">>100"&@cr)
ExitLoop(3)
EndIf
;~ ConsoleWrite($x1+66 &"," & $y1+44 & @CR)
;~ MsgBox(0,"",$x1+65&","&$y1+46)
ExitLoop(2)
EndIf
EndIf
EndIf
EndIf
Next
Next
_GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_ImageDispose($pBitmap)
;~ Sleep(1)
WEnd
_GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_ImageDispose($pBitmap)
_GDIPlus_Shutdown()
EndIf
EndSelect
WEnd
GUIDelete()
Como podéis comprobar no me he matado en el gui (ni en nada del código). He hecho esto porque es interesante que veáis como se puede trabajar con imágenes en memoria a gran velocidad.
Por supuesto creo que se puede conseguir más velocidad con apis que trabajan directamente con la tarjeta gráfica, como directx, opengl, etc, pero éstas son bastante complicadas, además de que las tienes que tener instaladas.
Con todo, añadir que seguramente hay alguna otra forma mejor de realizar esto. Es cuestión de buscar, leer, molestarse e interesarse.
En definitiva, autoit se defiende bastante bien en todo esto, pero pienso que para tratamientos gráficos y grandes operaciones serias, utilizaría otro lenguaje más rápido y estable, como por ejemplo java o .net.
Saludos.