AutoIt Do/Until Schleife bis Farbe da ist

01/18/2012 14:33 xFreshness#1
Hallo,
wie kann man in diesem Script in den Schleifen darstellen, dass wenn eine bestimme Farbe mit einer bestimmten Abweichung vorliegt, die Schleife eingeleitet oder beendet wird? Habs so probiert, geht aber nicht.
Kann jemand helfen?

01/18/2012 15:26 Fuii#2
Du kannst mit Hilfe der Funktion "AdlibRegister" eine Funktion alle X-Milisekunden aufrufen lassen - optimal für eine Farbsuche ohne Schleife.
Währenddessen macht dein Script einfach weiter (in meinem Beispiel wartet es einfach in der Skript-nötigen While-Schleife (z.B. für GUI-Input).

Code:
Global $aColorMode[3]
Global $Color1 = 0xFFB700, $Color2 = 0xFFFFFF

AdlibRegister("_Colorsearch", 500)	; Ruft die Funktion die Farbe zu suchen alle 500ms (jede halbe Sekunde) auf


While 1
	Sleep(100)
WEnd

Func _Colorsearch()
	Local $aColorArray
	$aColorMode[0] = 0

	send("{space down}")
	sleep(50)
	send("{space up}")
	Sleep(10)

	$aColorArray = PixelSearch(w,y,x,z, $Color1, 20)	; Farbe 1 nach der gesucht wird
	If Not @error Then	; Farbe 1 gefunden
		$aColorMode[0] = 1
		$aColorMode[1] = $aColorArray[0]	; PosX
		$aColorMode[2] = $aColorArray[1]	; PosY
	
	Else		; Farbe 1 nicht gefunden
		$aColorArray = PixelSearch(w,y,x,z, $Color2, 20); Farbe 2 nach der gesucht wird (nur wenn Farbe 1 nicht gefunden wurde)
		If Not @error Then 	; Farbe 2 gefunden
			$aColorMode[0] = 2
			$aColorMode[1] = $aColorArray[0]	; PosX
			$aColorMode[2] = $aColorArray[1]	; PosY
		EndIf
	EndIf

	If $aColorMode[0] > 0 Then _ColorFound($aColorMode[0])
EndFunc

Func _ColorFound($pMode)
	AdlibUnRegister("_Colorsearch")		; stopt den automatischen Aufruf der Such-Funktion
	Select
		Case $pMode = 1		; Wenn Farbe 1 gefunden wurde
			; was auch immer du hier machen willst

		Case $pMode = 2		; Wenn Farbe 2 gefunden wurde
			; ... what ever

		Case Else
			; Fehlermeldung
			MsgBox(48, "Error", "Unbekannter Modus: " & $pMode)
	EndSelect
EndFunc
01/18/2012 15:38 xFreshness#3
Vielleicht hätte ich erwähnen sollen, das erst nach dem einige male Enter, Space und "d" gedrückt wurde die Farbensuche beginnen darf. Dann befindet sich Fifa nämlich in einer Fussballpartie, es soll halt mit der Suche nach Schwarz überprüft werden, ob das Halbzeitpausenmenü schon da ist. Wenn das der Fall ist drückt der Bot es mit Enter weg, die 2. Halbzeit startet. Am Ende gibt es 2 Möglichkeiten eines Menüs- entweder man hat gewonnen, dann befindet sich bei xx,xx ein roter Pixel. Wenn nicht, irgendeine andere Farbe. Nachdem die Spielberichte weggedrückt wurden soll der Bot im Hauptmenü nicht mehr nach Farben suchen.
01/18/2012 15:49 Fuii#4
Was du davor oder danach machst, kannst du ja einfach einfügen.

Kurze Erklärung zu meinen Codeschnipsel:

Alle 500ms drückt er die Tasten:
send("{space down}")
sleep(50)
send("{space up}")
Sleep(10)

Danach sucht er nach Farbe 1 und 2. Wenn er eine von beiden gefunden hat, springt er in die Funktion "_ColorFound".
Dort kannst du bei Case = 1 bzw. Case = 2 definieren, was er machen soll, sobald er die jeweilige Farbe gefunden hat.

Sollte er keine der Farben gefunden haben, sucht er alle 500ms nach den beiden Farben (und drückt die 2 Tasten wieder), bis er eine von beiden gefunden hat.
01/18/2012 16:02 xFreshness#5
Klappt mittlerweile. Trotzdem Danke!
01/18/2012 16:51 Fuii#6
Naja, du hattest ja kurz deinen Code gepostet.
Du solltest es vermeiden alles innerhalb der While-Schleife des Skriptes zu haben.

Erstelle lieber einzelne Funktionen, die du immer wieder aufrufst, anstatt innerhalb der Skript-Schleife alles per Do-Until zu machen.

Z.B.:
Code:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Global $StateMatch = "Start"
Global $Color_HalbzeitEins = 0x373937, $Color_HalbzeitZwei = 0x181919
Opt("GUIOnEventMode", 1)

; Fenster zum Starten und Überwachen des aktuellen Fortschrittes
$W_Main 		= GUICreate("Form1", 208, 143, -1, -1)
$Btn_Start 		= GUICtrlCreateButton("Start", 64, 40, 75, 25)
$Ll_State 		= GUICtrlCreateLabel("Status: ", 16, 96, 40, 17)
$Ll_State_Dat 	= GUICtrlCreateLabel("Label2", 64, 96, 116, 33)

GUICtrlSetOnEvent($Btn_Start, "_GuiControl")
GUISetOnEvent($GUI_EVENT_CLOSE, "_GuiControl")
GUISetState(@SW_SHOW)

While 1
	Sleep(100)
WEnd

Func _GameController()
	AdlibRegister("_ShowGameState", 500)		; Generiert einen permanenten Tooltip mit aktuellen Informationen und aktualisiert das UI
	GUICtrlSetState($Btn_Start, $GUI_DISABLE)	; deaktiviert den Start-Button bis 1 Runde beendet wurde

	_Spielvorbereitung()
	_HalbZeitAktionen(1)
	_HalbZeitAktionen(2)

	GUICtrlSetState($Btn_Start, $GUI_ENABLE)	; aktiviert den Start-Button wieder
	_StopLoops()
EndFunc

Func _StopLoops()
	AdlibUnRegister("_ShowGameState")
	AdlibUnRegister("_GameController")
EndFunc

Func _Spielvorbereitung()
	$StateMatch = "Vorbereitung"
	Sleep(10000)
	Send("{Enter}")
	Sleep(1000)
	Send("{Enter}")
	Sleep(1000)
	Send("{down}")
	Sleep(1000)
	Send("{Enter}")
	Sleep(1000)

	; Turnierauswahl
	Send("{Left}")
	Sleep(1000)
	Send("{Enter}")
	Sleep(400)
	Send("{Up}")
	Sleep(250)
	Send("{Enter}")
	Sleep(1000)

	; Spielplan
	For $i = 1 To $i = 7 Step 1
		Send("{Enter}")
		Sleep(1500)
	Next
EndFunc

Func _HalbZeitAktionen($pHalbzeit = 1)
	Local $Farbe
	Select
		Case $pHalbzeit = 1		; 1. Halbzeit
			$StateMatch = "1. Halbzeit"
			Do
				Sleep(10)
				Send("{d down}")
				Sleep(1000)
				Send("{d up}")
				send("{space down}")
				sleep(50)
				send("{space up}")
				Sleep(10)
				$Farbe = PixelGetColor (560, 520)

			Until $Farbe = $Color_HalbzeitEins

			send("{enter}")
			Sleep(1000)

		Case $pHalbzeit = 2		; 2. Halbzeit
			$StateMatch = "2. Halbzeit"
			Do
				Sleep(10)
				Send("{d down}")
				Sleep(1000)
				Send("{d up}")
				send("{space down}")
				sleep(50)
				send("{space up}")
				Sleep(10)
				$Farbe = PixelGetColor (112, 972)

			Until $Farbe = $Color_HalbzeitZwei
	EndSelect
EndFunc

Func _ShowGameState($pInfo = 0)
	Local $tDisplaypData

	Select
		Case $pInfo = 0	; Standard: Zeigt aktuellen Spielstatus
			$tDisplaypData = "Aktueller Spielstatus: " & $StateMatch

		Case $pInfo = 1 ; Skript pausiert
			$tDisplaypData = "Skript pausiert!" & @CRLF & "Spielstatus: " & $StateMatch
	EndSelect

	ToolTip($tDisplaypData, -1, -1, "Fortschritt")	; aktualisiert den Tooltip
	GUICtrlSetData($Ll_State_Dat, $tDisplaypData)	; aktualisiert das GUI
EndFunc

Func _GuiControl()
	Select
		Case @GUI_CtrlId = $GUI_EVENT_CLOSE	; schließen button des Fenster gedrückt
			Exit
		Case @GUI_CtrlId = $Btn_Start		; start gedrückt
			AdlibRegister("_GameController")
	EndSelect
EndFunc
01/19/2012 22:43 xFreshness#7
Ich bin noch Anfänger in Auto-It,werde das in Zukunft dann auch in einzelne Funktionen teilen. Jetzt war ich gerade dabei mein Skript zu verbessern, es funktioniert zwar, aber an manchen stellen zu langsam. Diesen Teil hab ich geändert. Allerdings funktioniert PixelGetColor nicht, er führt immer den Else Teil der Schleife aus obwohl die Farbe 100%tig an der Stelle 1E1F1E ist (hab extra nochmal nur ein PixelGetColor Skript geschrieben und per MsgBox kam die auch raus). :confused:
Was ist daran bitte falsch?!

01/19/2012 22:53 KDeluxe#8
Code:
If Hex($farbe, 6)='1E1F1E'
Das kann nicht funktionieren. Du versucht eine Zahl mit einem String zu vergleichen, was in AutoIt eigentlich noch möglich wäre, wenn der String nur Zahlen enthalten würde.
Richtig wäre es so:
Code:
If Hex($Farbe) == 0x1E1F1E Then
;oder einfach:
If $Farbe == 0x1E1F1E Then
Die einzelnen Sachen in mehrere Funktionen aufzuteilen ist außerdem nur dann sinnvoll, wenn diese Codestücke öfters verwendet werden. Wenn du sie nur einmal in der While-Schleife brauchst, hat es keinen Sinn sie in Funktionen aufzuteilen.
01/19/2012 23:10 xFreshness#9
Gut das hab ich geändert. Geht aber trotzdem noch nicht, er findet die Farbe nicht. Ich hab hier nochmal einen Screenshot. Bei 976,684 liegt die Farbe 0x1E1F1E vor, aber es klappt einfach nicht. Kann AutoIt evtl. bei Vollbildspielen die Farbe nicht richtig auslesen? Vielleicht hat es auch was damit zu tun: Bei Fifa hat man bei Screenshots das Problem, das sie komplett grau sind, wenn man sie über die Druck Taste macht. Mit Fraps klappt es.
[Only registered and activated users can see links. Click Here To Register...]
01/19/2012 23:16 lolkop#10
der Hex(...) befehl hat doch aber als rückgabe wert einen string :P
es ist zwar einfacher direkt die farbe mit dem hex-wert zu vergleichen, aber das kann nicht die fehlerquelle sein =)

Edit:
um herauszufinden wo das problem liegt, musst du schon für realistische bedinungen sorgen, und in einer dauerschleife das ganze checken.

hier mal ein beispiel-tool für den dauercheck auf den pixel:
Code:
Dim $color, $tmp
While Sleep(50)
	$color = PixelGetColor(976,684)
	ToolTip('0x'&Hex($color))
	If $color<>$tmp Then
		MsgBox(0, 'Notice', 'Die Farbe auf dem Pixel hat sich geändert auf 0x'&Hex($color))
		$tmp=$color
	EndIf
WEnd
01/19/2012 23:32 xFreshness#11
Quote:
Originally Posted by lolkop View Post
Code:
Dim $color, $tmp
While Sleep(50)
	$color = PixelGetColor(976,684)
	ToolTip('0x'&Hex($color))
	If $color<>$tmp Then
		MsgBox(0, 'Notice', 'Die Farbe auf dem Pixel hat sich geändert auf 0x'&Hex($color))
		$tmp=$color
	EndIf
WEnd
Ich verstehe das Skript nicht genau. Er schreibt in $color die Farbe rein, gibt sie als Hex aus. Color ist ungleich $tmp, also gibt er wieder, aber in einer MsgBox aus, das gleiche aus. Wie funktioniert der dann permanent?
01/19/2012 23:48 KDeluxe#12
$tmp übernimmt nach der ersten MsgBox() den Wert von $color. Die MsgBox() wird also nur dann wieder ausgegeben, wenn sich die Farbe des Pixels ändert uns sich somit der aktuelle Farbwert ($color) vom alten Wert ($tmp) unterscheidet. Bleibt die Farbe des Pixels immer gleich, wirst du nur einmal eine MsgBox() Ausgabe bekommen.
01/19/2012 23:50 lolkop#13
Quote:
Originally Posted by xFreshness View Post
Ich verstehe das Skript nicht genau. Er schreibt in $color die Farbe rein, gibt sie als Hex aus. Color ist ungleich $tmp, also gibt er wieder, aber in einer MsgBox aus, das gleiche aus. Wie funktioniert der dann permanent?
ich war davon ausgegengen, das du dir sicher bist, das der pixel dauerhaft diese farbe hat. so kannst du testen ob dies wirklich der fall ist.
sobald die farbe sich ändert popt hier eine msgbox auf, welche dich darauf hinweist.

interesannt hieran ist, ob tatsächlich die farbe ausgelesen wird, von welcher du hier ausgehst.
01/19/2012 23:55 xFreshness#14
Laut deinem Pixelchecker ist die Farbe: 0x001E1F1E.
Warum sind das denn 8 Zahlen nach dem x?
01/20/2012 00:02 lolkop#15
weil autoit im normalfall mit dword/int hex werten arbeitet.

poste bitte einmal dein gesamtes script hier, damit wir nachvollziehen können warum du im <then case> ein exitloop auf level 2 ebene anwendest.