Hallo,
Da ich gestern beim Vorstellungsgespräch nach Codebeispielen gefragt wurde, die ich schicken könnte, habe ich mir überlegt noch schnell einen Snake-Klon zu schreiben.
Nichts weltbewegendes, aber er macht schonmal Spaß.
Steuerung und Spielprinzip sollten eigentlich klar sein, aber ich erklär es nochmal:
Pfeiltasten benutzen um der Schlange eine neue richtung zuzuweisen.
Ziel ist es, so lange durchzuhalten wie möglich, und so viel Beute wie möglich aufzusammeln.
Viel Spaß damit
(Mein Rekord : 194941 - hab aber nicht exessiv gespielt)
Spoiler anzeigen
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <Timers.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
OnAutoItExitRegister("__GDIPlus_Shutdown")
;General GDI+ Vars
Global $SCALE = 1.75
Global $hGUI, $iWidth = 200 * $SCALE, $iHeight = 200 * $SCALE
Global $GUI_Back_Color = 0xFFF0F0F0
Global $hBackbuffer, $hBrush, $hBrushFood, $hGraphic, $hBitmap
;Game Vars
Global $PL_THICKNESS = $iWidth / 20, $PL_SPEED = 2
Global $aTimers[2], _ ; [timers] -> 0: movement | 1: Full Playtime
$PL_MOV_CUR, $PL_JUST_CHANGED_DIR, _
$aPL_POSITIONS[3][2]
Global Enum _
$PL_MOV_NONE, _
$PL_MOV_UP, _
$PL_MOV_LEFT, _
$PL_MOV_DOWN, _
$PL_MOV_RIGHT
Global $FOOD_ISACTIVE, $FOOD_COORD[2]
[/autoit] [autoit][/autoit] [autoit]$hDLL = DllOpen("user32.dll")
_GDI_StartUp()
While 1
_NewDirection()
_GDIPlus_GraphicsClear($hBackbuffer, $GUI_Back_Color)
_DrawTimerHandler()
_WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT)
WEnd
#region - Essential GDI+ Functions
Func _GDI_StartUp()
;Create GUI as background.
$hGUI = GUICreate("GDI+ Snake [SEuBo]", $iWidth, $iHeight)
GUISetOnEvent(-3, "OnEvent_Eventhandler")
GUIRegisterMsg($WM_PAINT, "WM_PAINT")
;Startup GDI+ Engine
_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBrush = _GDIPlus_BrushCreateSolid()
$hBrushFood = _GDIPlus_BrushCreateSolid(0xFFFF3535)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic)
$hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
;Set Timers for Movement/Special/Boni
For $i = 0 To UBound($aTimers) - 1
$aTimers[$i] = TimerInit()
Next
For $i = 0 To UBound($aPL_POSITIONS) - 1
$aPL_POSITIONS[$i][0] = Floor($iWidth) / 2 - Mod($iWidth / 2, $PL_THICKNESS) - $PL_THICKNESS
$aPL_POSITIONS[$i][1] = Floor($iHeight) / 2 - Mod($iHeight / 2, $PL_THICKNESS) - $PL_THICKNESS
Next
GUISetState()
EndFunc ;==>_GDI_StartUp
Func WM_PAINT()
_WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_UPDATENOW)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iWidth, $iHeight)
_WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_VALIDATE)
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_PAINT
Func __GDIPlus_Shutdown()
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()
EndFunc ;==>__GDIPlus_Shutdown
#endregion - Essential GDI+ Functions
#region - Game Funktions
Func _DrawTimerHandler()
;Draw Player
If TimerDiff($aTimers[0]) > 500 / $PL_SPEED + 25 Then
_DrawPlayer(1)
$aTimers[0] = TimerInit()
Else
_DrawPlayer(0)
EndIf
;Draw Food
_DrawFood($FOOD_ISACTIVE = False)
;Draw More stuff
;...
EndFunc ;==>_DrawTimerHandler
[/autoit] [autoit][/autoit] [autoit]Func _DrawPlayer($iFlag)
Local $iUB = UBound($aPL_POSITIONS)
If $iFlag Then
For $i = $iUB - 1 To 1 Step -1
$aPL_POSITIONS[$i][0] = $aPL_POSITIONS[$i - 1][0]
$aPL_POSITIONS[$i][1] = $aPL_POSITIONS[$i - 1][1]
Next
$aPL_POSITIONS[0][0] = $aPL_POSITIONS[0][0] + (($PL_MOV_CUR = $PL_MOV_RIGHT) * $PL_THICKNESS) - (($PL_MOV_CUR = $PL_MOV_LEFT) * $PL_THICKNESS)
$aPL_POSITIONS[0][1] = $aPL_POSITIONS[0][1] + (($PL_MOV_CUR = $PL_MOV_DOWN) * $PL_THICKNESS) - (($PL_MOV_CUR = $PL_MOV_UP) * $PL_THICKNESS)
If $aPL_POSITIONS[0][0] >= $iWidth Then $aPL_POSITIONS[0][0] = 0
If $aPL_POSITIONS[0][0] < 0 Then $aPL_POSITIONS[0][0] = $iWidth - $PL_THICKNESS
If $aPL_POSITIONS[0][1] >= $iHeight Then $aPL_POSITIONS[0][1] = 0
If $aPL_POSITIONS[0][1] < 0 Then $aPL_POSITIONS[0][1] = $iHeight - $PL_THICKNESS
$PL_JUST_CHANGED_DIR = False
[/autoit] [autoit][/autoit] [autoit]_PlayerAteFood(($aPL_POSITIONS[0][0] = $FOOD_COORD[0]) And ($aPL_POSITIONS[0][1] = $FOOD_COORD[1]))
[/autoit] [autoit][/autoit] [autoit]If _CoordsAlreadyUsedByPlayer($aPL_POSITIONS[0][0], $aPL_POSITIONS[0][1], 1) Then Exit MsgBox(64, "Game over!", "Herzlichen Glückwunsch, du hast " & Floor(TimerDiff($aTimers[1]) / 100 * UBound($aPL_POSITIONS)) & " Punkte erreicht!" & @CRLF)
[/autoit] [autoit][/autoit] [autoit]EndIf
For $i = 0 To $iUB - 1
_GDIPlus_GraphicsFillRect($hBackbuffer, $aPL_POSITIONS[$i][0], $aPL_POSITIONS[$i][1], $PL_THICKNESS, $PL_THICKNESS, $hBrush)
Next
EndFunc ;==>_DrawPlayer
Func _DrawFood($iFlag)
If $iFlag Then
Do
$FOOD_COORD[0] = Random(0, $iWidth - $PL_THICKNESS)
$FOOD_COORD[1] = Random(0, $iHeight - $PL_THICKNESS)
$FOOD_COORD[0] -= Mod($FOOD_COORD[0], $PL_THICKNESS)
$FOOD_COORD[1] -= Mod($FOOD_COORD[1], $PL_THICKNESS)
Until Not _CoordsAlreadyUsedByPlayer($FOOD_COORD[0], $FOOD_COORD[1])
$FOOD_ISACTIVE = True
EndIf
_GDIPlus_GraphicsFillRect($hBackbuffer, $FOOD_COORD[0], $FOOD_COORD[1], $PL_THICKNESS, $PL_THICKNESS, $hBrushFood)
EndFunc ;==>_DrawFood
Func _PlayerAteFood($fBool)
Local Static $iFoodQueue
If $fBool Then
Local $iUB = UBound($aPL_POSITIONS)
ReDim $aPL_POSITIONS[$iUB + 1][2]
$aPL_POSITIONS[$iUB][0] = $aPL_POSITIONS[$iUB - 1][0]
$aPL_POSITIONS[$iUB][1] = $aPL_POSITIONS[$iUB - 1][1]
$FOOD_ISACTIVE = False
$iFoodQueue += 1
If $iFoodQueue = 5 Then
$PL_SPEED += 0.5
$iFoodQueue = 0
EndIf
EndIf
EndFunc ;==>_PlayerAteFood
Func _CoordsAlreadyUsedByPlayer($iX, $iY, $iStart = 0)
If $PL_MOV_CUR = $PL_MOV_NONE Then Return False
For $i = $iStart To UBound($aPL_POSITIONS) - 1
If $iX = $aPL_POSITIONS[$i][0] And $iY = $aPL_POSITIONS[$i][1] Then Return True
Next
Return False
EndFunc ;==>_CoordsAlreadyUsedByPlayer
#endregion - Game Funktions
Func OnEvent_Eventhandler()
Switch @GUI_CtrlId
Case -3
Exit
EndSwitch
EndFunc ;==>OnEvent_Eventhandler
Func _NewDirection()
[/autoit] [autoit][/autoit] [autoit]If _IsPressed(26, $hDLL) Then
If $PL_MOV_CUR <> $PL_MOV_DOWN And $PL_MOV_CUR <> $PL_MOV_UP Then __NewDirection($PL_MOV_UP)
EndIf
If _IsPressed(25, $hDLL) Then ; left
If $PL_MOV_CUR <> $PL_MOV_RIGHT And $PL_MOV_CUR <> $PL_MOV_LEFT Then __NewDirection($PL_MOV_LEFT)
EndIf
If _IsPressed(28, $hDLL) Then ; down
If $PL_MOV_CUR <> $PL_MOV_UP And $PL_MOV_CUR <> $PL_MOV_DOWN Then __NewDirection($PL_MOV_DOWN)
EndIf
If _IsPressed(27, $hDLL) Then ; right
If $PL_MOV_CUR <> $PL_MOV_LEFT And $PL_MOV_CUR <> $PL_MOV_RIGHT Then __NewDirection($PL_MOV_RIGHT)
EndIf
EndFunc ;==>_NewDirection
[/autoit] [autoit][/autoit] [autoit]Func __NewDirection($PL_NEW_DIRECTION = -1) ;Internal
Local Static $KEY_BUFFER, $KEY_BUFFERTIMER
If $PL_JUST_CHANGED_DIR Then
$KEY_BUFFER = $PL_NEW_DIRECTION
_Timer_KillTimer($hGUI, $KEY_BUFFERTIMER)
Return
EndIf
If $PL_NEW_DIRECTION = -1 Then
$PL_MOV_CUR = $KEY_BUFFER
$KEY_BUFFERTIMER = _Timer_SetTimer($hGUI, 500 / $PL_SPEED * 0.75, "__NewDirection")
Return
EndIf
$PL_MOV_CUR = $PL_NEW_DIRECTION
$PL_JUST_CHANGED_DIR = True
EndFunc ;==>__NewDirection