GDI+: Wieso sieht das abgespeicherte Bild anders aus als das vorher dargestellte?

  • Hallo,

    ich hab ein Problem bei meinem PacMan-Spiel. Unzwar mach ich ja alle Darstellungen mit GDI+. Nun hab ich ja die Animation von dem PacMan, das man ihn bewegen kann und das sein Mund auf und zu geht. Und den Hintergrund erstelle ich mit einem Array. Siehe Code. Wenn man jetzt den PacMan steuert muss er ja immer neu gezeichnet werden und dann muss ich auch immer den Hintergrund neuzeichnen. Aber wenn ich den Hintergrund immer neu zeichne, ist das Spiel immer so träge, deswegen will ich am Anfang einmal den Hintergrund zeichnen und dann wieder laden und halt dann immer mit _GDIPlus_GraphicsDrawImageRect anzeigen. Aber das abgespeicherte Bild sieht anders aus als das was ich am Anfang erstelle, siehe Bilder.

    vorher:
    autoit.de/wcf/attachment/9216/

    nachher abgespeichert:
    autoit.de/wcf/attachment/9217/


    Code:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <GDIPlus.au3>
    #include <GUIConstants.au3>
    #include <Misc.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    Global $aEnableForGo[4] ; [links, oben, rechts, unten]
    Global $Timer
    Global $iWidth = 600
    Global $iHeight = 600
    Global $iX = 500
    Global $iY = 200
    Global $iAngleStart = 20
    Global $iAngleEnd = 320
    Global $piewidth = 0
    Global $pieheight = 320
    Global $aSquarePos[2]
    Global $aBG[12][12] = [[1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0], _
    [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0], _
    [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0], _
    [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1], _
    [1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1], _
    [1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0], _
    [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], _
    [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1], _
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1], _
    [1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0], _
    [1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], _
    [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]]

    [/autoit] [autoit][/autoit] [autoit]

    Global $aPoints = $aBG

    [/autoit] [autoit][/autoit] [autoit]

    $hDLL = DllOpen("user32.dll")

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("PacMan made by m-obi", $iWidth, $iHeight)
    GUISetBkColor(0xFFFFFF)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup ()

    [/autoit] [autoit][/autoit] [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

    [/autoit] [autoit][/autoit] [autoit]

    $pac = _GDIPlus_BrushCreateSolid(0xFFFFFF00)
    $Brush1 = _GDIPlus_BrushCreateSolid(0xFFEEEEEE)
    $Brush2 = _GDIPlus_BrushCreateSolid(0xFF000000)
    $Brush3 = _GDIPlus_BrushCreateSolid(0xFF636363)
    _BG()
    ;$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Map.jpg")

    [/autoit] [autoit][/autoit] [autoit]

    AdlibRegister("_AniPacMan", 400)
    AdlibRegister("_SquarePos", 50)

    [/autoit] [autoit][/autoit] [autoit]

    While 1

    [/autoit] [autoit][/autoit] [autoit]

    If TimerDiff($Timer) > 200 Then _Draw(1)

    [/autoit] [autoit][/autoit] [autoit]

    ;ToolTip($aSquarePos[0] & @CRLF & $aSquarePos[1])

    [/autoit] [autoit][/autoit] [autoit]

    If $aSquarePos[0] > 0.9 Then $aEnableForGo[0] = $aBG[Int($aSquarePos[1])][Int($aSquarePos[0]) - 1]
    If $aSquarePos[1] > 0.9 Then $aEnableForGo[1] = $aBG[Int($aSquarePos[1]) - 1][Int($aSquarePos[0])]
    If $aSquarePos[0] < 11 Then $aEnableForGo[2] = $aBG[Int($aSquarePos[1])][Int($aSquarePos[0]) + 1]
    If $aSquarePos[1] < 11 Then $aEnableForGo[3] = $aBG[Int($aSquarePos[1]) + 1][Int($aSquarePos[0])]

    [/autoit] [autoit][/autoit] [autoit]

    $aEnableForGo[0] = _Iif($aSquarePos[0] = 0.5 Or (Not $aEnableForGo[0] And StringRight($aSquarePos[0], 1) = 5), 0, 1)
    $aEnableForGo[1] = _Iif($aSquarePos[1] = 0.5 Or (Not $aEnableForGo[1] And StringRight($aSquarePos[1], 1) = 5), 0, 1)
    $aEnableForGo[2] = _Iif($aSquarePos[0] = 11.5 Or (Not $aEnableForGo[2] And StringRight($aSquarePos[0], 1) = 5), 0, 1)
    $aEnableForGo[3] = _Iif($aSquarePos[1] = 11.5 Or (Not $aEnableForGo[3] And StringRight($aSquarePos[1], 1) = 5), 0, 1)

    [/autoit] [autoit][/autoit] [autoit]

    If StringRight($aSquarePos[0], 1) = 5 Then
    Select
    Case _IsPressed("26", $hDLL) And $aEnableForGo[1] ;oben
    $iAngleStart = 290
    $iY -= 10
    _Draw()
    Case _IsPressed("28", $hDLL) And $aEnableForGo[3] ;unten
    $iAngleStart = 110
    $iY += 10
    _Draw()
    EndSelect
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If StringRight($aSquarePos[1], 1) = 5 Then
    Select
    Case _IsPressed("25", $hDLL) And $aEnableForGo[0] ;links
    $iAngleStart = 200
    $iX -= 10
    _Draw()
    Case _IsPressed("27", $hDLL) And $aEnableForGo[2] ;rechts
    $iAngleStart = 20
    $iX += 10
    _Draw()
    EndSelect
    EndIf

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Draw($iTyp = 0)
    _BG()
    While 1
    Switch $iTyp
    Case 0
    $iTyp = _Iif(TimerDiff($Timer) > 200, 1, 2)
    Case 1
    _GDIPlus_GraphicsFillPie($hBuffer, $iX, $iY, 50, 50, $iAngleStart, $iAngleEnd, $pac)
    ExitLoop
    Case 2
    _GDIPlus_GraphicsFillPie($hBuffer, $iX, $iY, 50, 50, $iAngleStart - 15, $iAngleEnd + 30, $pac)
    ExitLoop
    EndSwitch
    WEnd
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iWidth, $iHeight)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _DrawPoints()
    If StringRight($aSquarePos[0], 1) = 5 And StringRight($aSquarePos[1], 1) = 5 Then $aPoints[Int($aSquarePos[1])][Int($aSquarePos[0])] = 0
    For $y = 0 To UBound($aPoints) - 1
    For $x = 0 To UBound($aPoints, 2) - 1
    If $aPoints[$y][$x] Then _GDIPlus_GraphicsFillEllipse($hBuffer, $x * 50 + 15, $y * 50 + 15, 20, 20, $Brush3)
    Next
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _GDIPlus_BrushDispose($pac)
    _GDIPlus_BrushDispose($Brush1)
    _GDIPlus_BrushDispose($Brush2)
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    DllClose($hDLL)
    Exit
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _AniPacMan()
    _Draw(2)
    $Timer = TimerInit()
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _BG()
    For $y = 0 To UBound($aBG) - 1
    For $x = 0 To UBound($aBG, 2) - 1
    If $aBG[$y][$x] Then
    _GDIPlus_GraphicsFillRect($hBuffer, $x * 50, $y * 50, 50, 50, $Brush1)
    Else
    _GDIPlus_GraphicsFillRect($hBuffer, $x * 50, $y * 50, 50, 50, $Brush2)
    EndIf
    Next
    Next
    _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\Map.jpg")
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _SquarePos()
    $aSquarePos[0] = ($iX / 50) + 0.5
    $aSquarePos[1] = ($iY / 50) + 0.5
    EndFunc

    [/autoit]
  • Wer sagt, daß das gesamte Spielfeld neu gezeichnet werden muss, nur weil sich die Spielfigur einige Pixel weiterbewegt bzw, sich auf der Stelle bewegt?
    Angenommen, dein "Pacman" ist 20x20 Pixel groß und bewegt sich immer 2 Pixel weit. Dann musst du nur die Umgebung an der neuen Position deines Pacmans aus der Hintergrunddatei laden (25x25 Pixel), an die neue Position zeichen und den Pacman drüberzeichnen. Da der Pacman sich nur maximal 2 Pixel weit bewegt, wird die alte Position immer ubermalt.
    Sehr gut und vorallem sehr schnell funktioniert das per _WinApi_BitBlt(), allerdings geht das auch mit GDI+.

    Bezüglich des "falsch" abgespeicherten Bildes kann man ohne Script nicht viel sagen...

  • Andy: Danke für den Hinweis, den werde ich mal ausprobieren. Klingt logischer wenn ich nur den Bereich neuzeichnen lasse, wo sich auch der PacMan befindet. Spart an Zeit.

    Edit: Man muss ja die Threads pflegen, deswegen wollt ich nur sagen, das der Hinweis funktioniert. ;) Script wird es vollständig geben, wenn das Spiel fertig ist oder halt auf Anfrage.

    Einmal editiert, zuletzt von m-obi (4. Mai 2010 um 16:46)