Hi liebe Community,
da ich etwas mit GDI+ üben wollte hab ich versucht Snake zu schreiben (nix besonderes)
Als Vorlage für die Logik hab ich ein von mir früher geschriebenes C Programm genutzt.
Die Umsetzung ist mir eigentlich ganz gut gelungen und funktioniert auch derweil.
Um die Bewegung recht flüßig zu gestalten, hab ich den eigentlichen Schritt "Bewege und Zeichne Schlange 1 Feld weiter" auf 8 Zeichenschritte aufgeteilt.
Allerdings hab ich gemerkt, dass wenn die Selbstkollision der Schlange und Wandkollision aktiv sind, die Performance darunter leidet (wohl wegen den _ArraySearch).
Gibts ne Möglichkeit das effektiv besser zu gestalten?
Bin für Kritik usw. offen.
Hier das Script, die benötigten Bilddateien sind angehängt.
Gruß
Prajoss
PS: Hab das wichtigste kommentiert
Script
#include <GDIPlus.au3>
#include <GUIConstants.au3>
#include <Misc.au3>
#include <String.au3>
#include <Color.au3>
#include <Array.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
;~ Variablen initialisieren
[/autoit] [autoit][/autoit] [autoit]Global $hWnd_main
Global $GuiHeight = 400
Global $GuiWidth = 600
Global $SnakeHeight = 20
Global $SnakeWidth = 20
Global $MausHeight = 20
Global $MausWidth = 20
Global $Snakecolor = 0xFFFFFFFF
Global $Schweifcolor = 0xFFFF0000
Global $Snake_X[1000] ; X Koordinate der Schlange + Schweif
Global $Snake_Y[1000] ; Y Koordinate der Schlange + Schweif
$Snake_Y[0] = $GuiHeight / 2 ; Startposition
$Snake_X[0] = $GuiWidth / 2 ; Startposition
Global $Maus_X
Global $Maus_Y
_Maus_erzeugen() ; Erste Maus erzeugen
[/autoit] [autoit][/autoit] [autoit]Global $Snakestep_X[1000][2] ; Array für die horizontale Richtungen der einzelnen Schlangenteile
Global $Snakestep_Y[1000][2] ; Array für die vertikale Richtungen der einzelnen Schlangenteile
;~ Snakestep_[][0] ist dabei die aktuelle Bewegungsrichtung
;~ Snakestep_[][1] ist dabei die alte Bewegungsrichtung
$Snakestep_X[0][0] = 0 ;Startrichtung
$Snakestep_Y[0][0] = 0 ;Startrichtung
Global $Snake_Laenge = 0 ; Größe der Schlange (Kopf zählt nicht dazu!)
[/autoit] [autoit][/autoit] [autoit]Global $Option1 = 0
Global $Option2 = 0
Global $Option3 = 0
Global $Punkte
HotKeySet("{SPACE}", "_pause")
HotKeySet("^o", "_options")
;~ Erzeugen des Spielfelds
[/autoit] [autoit][/autoit] [autoit]$hWnd_main = GUICreate( "Snake v 0.1", $GuiWidth, $GuiHeight)
GUISetState(@SW_SHOW)
;~ Pfade für die Grafiken
[/autoit] [autoit][/autoit] [autoit]Global $Background_path = @ScriptDir & "\map.png"
Global $Image_Maus = @ScriptDir & "\maus.png"
;~ GDI_Plus für Grafiken
[/autoit] [autoit][/autoit] [autoit]_GDIPlus_Startup()
[/autoit] [autoit][/autoit] [autoit]Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd_main)
[/autoit] [autoit][/autoit] [autoit]Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($GuiWidth, $GuiHeight, $hGraphic)
Global $hGraphic_Buffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGraphic_Buffer, 2)
Global $hBackground = _GDIPlus_ImageLoadFromFile($Background_path)
_GDIPlus_GraphicsDrawImageRect($hGraphic_Buffer, $hBackground, 0, 0, $GuiWidth, $GuiHeight)
Global $hBrush_Snake = _GDIPlus_BrushCreateSolid($Snakecolor)
Global $hMaus = _GDIPlus_ImageLoadFromFile($Image_Maus)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hMaus, $Maus_X, $Maus_Y, $MausHeight, $MausWidth)
Global $hBrush_Schweif = _GDIPlus_BrushCreateSolid($Schweifcolor)
[/autoit] [autoit][/autoit] [autoit];~ main
[/autoit] [autoit][/autoit] [autoit]While True
$msg = GUIGetMsg()
If $msg == $GUI_EVENT_CLOSE Then
_Exit()
EndIf
;~ Ändere die Richtung falls das Programm aktiv ist
If Not WinActive($hWnd_main) = 0 Then
If _IsPressed("27") And $Snakestep_X[0][0] == 0 Then
$Snakestep_X[0][0] = 2.5
$Snakestep_Y[0][0] = 0
ElseIf _IsPressed("25") And $Snakestep_X[0][0] == 0 Then
$Snakestep_X[0][0] = -2.5
$Snakestep_Y[0][0] = 0
ElseIf _IsPressed("26") And $Snakestep_Y[0][0] == 0 Then
$Snakestep_Y[0][0] = -2.5
$Snakestep_X[0][0] = 0
ElseIf _IsPressed("28") And $Snakestep_Y[0][0] == 0 Then
$Snakestep_Y[0][0] = 2.5
$Snakestep_X[0][0] = 0
EndIf
EndIf
;~ Zeichenfunktion
[/autoit] [autoit][/autoit] [autoit]_Draw()
DllCall("Psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
;~ Deaktivieren des Optionsmenü nach der ersten Bewegung
If $Snakestep_X[0][0] <> 0 Or $Snakestep_Y[0][0] <> 0 Then
HotKeySet("^o")
EndIf
WEnd
Func _Draw()
For $x = 1 to 8
_GDIPlus_GraphicsDrawImageRect($hGraphic_Buffer, $hBackground, 0, 0, $GuiWidth, $GuiHeight)
_GDIPlus_GraphicsDrawImageRect($hGraphic_Buffer, $hMaus, $Maus_X, $Maus_Y, $MausHeight, $MausWidth)
_Schweif_zeichnen()
_GDIPlus_GraphicsFillEllipse($hGraphic_Buffer, $Snake_X[0], $Snake_Y[0], $SnakeWidth, $SnakeHeight, $hBrush_Snake)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $GuiWidth, $GuiHeight)
;~ Übernehmen der Richtung des Schweifes
For $i = 1 To $Snake_Laenge
$Snakestep_X[$i][0] = $Snakestep_X[$i-1][1]
$Snakestep_Y[$i][0] = $Snakestep_Y[$i-1][1]
Next
;~ Bewegung der Schlange
For $i = 0 To $Snake_Laenge
$Snake_X[$i] = $Snake_X[$i] + $Snakestep_X[$i][0]
$Snake_Y[$i] = $Snake_Y[$i] + $Snakestep_Y[$i][0]
Next
;~ Option 1
_Pruefe_Wandkollision()
;~ Option 2
_Pruefe_Eigenkollision()
;~ Maus wird gefressen
If $Snake_X[0] == $Maus_X And $Snake_Y[0] == $Maus_Y Then
_Maus_erzeugen()
$Snake_Laenge = $Snake_Laenge + 1
$Snake_X[$Snake_Laenge] = $Snake_X[$Snake_Laenge - 1] - ($Snakestep_X[$Snake_Laenge - 1][0] *
$Snake_Y[$Snake_Laenge] = $Snake_Y[$Snake_Laenge - 1] - ($Snakestep_Y[$Snake_Laenge - 1][0] *
EndIf
;~ Einbinden der 3. Option (Maus verschwindet nach Zeit)
;~ If $Option3 == 1 Then
;~
;~ EndIf
;~ Übergeben der Richtung an den nächsten Teil der Schlange
[/autoit] [autoit][/autoit] [autoit]If $x == 8 Then
For $i = 0 To $Snake_Laenge
$Snakestep_X[$i][1] = $Snakestep_X[$i][0]
$Snakestep_Y[$i][1] = $Snakestep_Y[$i][0]
Next
EndIf
Next
[/autoit] [autoit][/autoit] [autoit]Sleep(10)
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]Func _Schweif_zeichnen()
For $i = 1 To $Snake_Laenge
_GDIPlus_GraphicsFillEllipse($hGraphic_Buffer, $Snake_X[$i], $Snake_Y[$i], $SnakeWidth, $SnakeHeight, $hBrush_Schweif)
Next
EndFunc
Func _Maus_erzeugen()
Do
$Maus_X = Random(1, 28, 1) * $MausWidth
$Maus_Y = Random(1, 18, 1) * $MausHeight
; Sicherstellen, dass die Maus nicht in der Schlange erzeugt wird
Until Not (_ArraySearch($Snake_X, $Maus_X) == _ArraySearch($Snake_Y, $Maus_X) And _ArraySearch($Snake_X, $Snake_X[0], 5) > 0 )
EndFunc
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]Func _options()
GUISetState(@SW_HIDE, $hWnd_main)
$hWnd_options = GUICreate("Snake v 0.1 Options", 280, 110)
$Checkbox1 = GUICtrlCreateCheckbox("Wall-Walk", 30, 20, 250, 17)
$Checkbox2 = GUICtrlCreateCheckbox("Selbstkollision ausschalten", 30, 50, 250, 17)
$Checkbox3 = GUICtrlCreateCheckbox("Mäuse verschwinden nach Zeit", 30, 80, 250, 17)
GUISetState(@SW_SHOW)
[/autoit] [autoit][/autoit] [autoit]While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
If BitAND(GUICtrlRead($Checkbox1), $GUI_CHECKED) Then $Option1 = 1
If BitAND(GUICtrlRead($Checkbox2), $GUI_CHECKED) Then $Option2 = 1
If BitAND(GUICtrlRead($Checkbox3), $GUI_CHECKED) Then $Option3 = 1
ExitLoop
EndSwitch
[/autoit] [autoit][/autoit] [autoit]Sleep(10)
WEnd
GUIDelete($hWnd_options)
GUISetState(@SW_SHOW, $hWnd_main)
EndFunc
Func _Pruefe_Wandkollision()
If $Option1 == 0 Then
If $Snake_X[0] > ($GuiWidth - $SnakeWidth - 20) Or $Snake_X[0] < 20 Or $Snake_Y[0] < 20 Or $Snake_Y[0] > ($GuiHeight - $SnakeWidth - 20) Then
_Verloren("Du bist gegen eine Wand gelaufen!")
EndIf
Else
For $i = 0 To $Snake_Laenge
If $Snake_X[$i] > ($GuiWidth - $SnakeWidth - 20) Then $Snake_X[$i] = $SnakeWidth + 2.5
If $Snake_Y[$i] > ($GuiHeight - $SnakeHeight - 20) Then $Snake_Y[$i] = $SnakeHeight + 2.5
If $Snake_X[$i] < 20 Then $Snake_X[$i] = ($GuiWidth - $SnakeWidth - 22.5)
If $Snake_Y[$i] < 20 Then $Snake_Y[$i] = ($GuiHeight - $SnakeHeight - 22.5)
Next
EndIf
EndFunc
Func _Pruefe_Eigenkollision()
If $Option2 == 0 Then
$x = _ArraySearch($Snake_X, $Snake_X[0], 4)
$y = _ArraySearch($Snake_Y, $Snake_Y[0], 4)
If $x == $y And $x > 0 Then
_Verloren("Du hast dich selbst gebissen!")
EndIf
EndIf
EndFunc
Func _Pause()
HotKeySet("{SPACE}")
_GDIPlus_GraphicsDrawImageRect($hGraphic_Buffer, $hBackground, 0, 0, $GuiWidth, $GuiHeight)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $GuiWidth, $GuiHeight)
While _IsPressed("20")
Sleep(10)
WEnd
While True
If GUIGetMsg() == $GUI_EVENT_CLOSE Then _Exit()
If _IsPressed("20") Then ExitLoop
Sleep(10)
WEnd
HotKeySet("{SPACE}", "_Pause")
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]Func _Verloren($str)
HotKeySet("{SPACE}")
MsgBox(0, "Snake v 0.1", $str & @CRLF & @CRLF & "Länge des Schweifs: " & $Snake_Laenge)
_Exit()
EndFunc
Func _Exit()
_GDIPlus_BrushDispose($hBrush_Snake)
_GDIPlus_GraphicsDispose($hGraphic_Buffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
Exit
EndFunc
[/autoit]