GDIPlus Jpg`s/gif`s übermalen

  • Hey,

    Ich wollte gerne mein eigendes Defender spiel schreiben, mein erster versuch war einfach nur mit GUICtrlSetPos doch das flakern hat mich aufgeregt. Deswegen habe ich googelt wie man es lösen kan & ich kam zu GDIPlus. Ich habe bereits ein Hintergrund, wo die Gegner herlaufen, und auch bereits einen gegner der die strecke lang läuft. Doch leider läst er sich ja nicht löschen, wenn ich ihn gekillt habe oder er durch gekommen ist. Ich weiß auch nicht wie ich ihn auf den hintergrund übermalen kan...

    Spoiler anzeigen

    Das sind bilder von dem Spiel, der code:

    Spoiler anzeigen
    [autoit]

    #include <GuiConstants.au3>
    #include <GdiPlus.au3>;das include
    #include <Misc.au3>

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

    OnAutoItExitRegister("_end") ; die Funktion _end am Ende des Scriptes ausführen
    Opt("GUIOnEventMode", 1)
    HotKeySet("{ENTER}","_WaveStart")
    Global $GegnerX = -50
    Global $GegnerY = 79
    Global $Start = False

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

    $Gui = GUICreate("Beispiel", 1000, 600)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup() ;Gdi starten

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

    $Map = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Map.jpg")
    $graphic = _GDIPlus_GraphicsCreateFromHWND($Gui)
    _GDIPlus_GraphicsDrawImageRect($graphic, $Map, 0, 0, 800, 600) ;die Figur wird an der neuen Position gezeichnet
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Gui);noramle Grafik erstellen
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(800, 600, $hGraphic);Buffer erstellen Schritt 1...
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap);...und 2
    GUISetOnEvent($GUI_EVENT_CLOSE, "_end")

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

    While 1
    If $Start = True Then
    _Move()
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Map, 0, 0, 800, 600);mit Buffer
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Gegner, $GegnerX, $GegnerY, 50, 50)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, 800, 600)
    EndIf
    WEnd

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

    Func _Move()
    if $GegnerX >= 635 and $GegnerY >= 436 Then
    _GDIPlus_GraphicsClear($hBuffer, 0xFF000000 + 0xF0F0F0)
    ElseIf $GegnerY = 79 and $GegnerX <= 648 Then
    $GegnerX = $GegnerX + 4
    ElseIf $GegnerX = 650 and $GegnerY <= 240 Then
    $GegnerY = $GegnerY + 4
    ElseIf $GegnerY = 243 and $GegnerX >= 115 Then
    $GegnerX = $GegnerX - 4
    ElseIf $GegnerX = 114 and $GegnerY <= 435 Then
    $GegnerY = $GegnerY + 4
    ElseIf $GegnerY = 439 and $GegnerX <= 637 Then
    $GegnerX = $GegnerX + 4
    EndIf
    EndFunc

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

    Func _WaveStart()
    HotKeySet("{ENTER}")
    Global $Gegner = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gegner1.jpg")
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Gegner, $GegnerX, $GegnerY, 20, 20)
    $Start = True
    EndFunc

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

    Func _end();die Exit funktion
    _GDIPlus_GraphicsDispose($graphic);Grafik Objekt freigeben
    _GDIPlus_ImageDispose($Map);Bild Objekt freigeben
    _GDIPlus_Shutdown();Ressourcen freigeben
    Exit
    EndFunc ;==>_end

    [/autoit]

    Da ich heute erst mit GDIPlus angefangen sind stamm viel aus dem Tut hier im forum ;)

    & Meine 2te frage, ist es möglich mehrere Gegner ans laufen zu bringen? Mit einem ist das ja zimlich langweilig :thumbdown:

    MfG Nico

    MfG Nico

    MfG - Mit freundlichen Grüssen

    die Welt liegt uns zu Füssen, den wir steh'n drauf

    wir geh'n drauf für ein Leben voller Schall und Rauch

    bevor wir fall'n, fall'n wir lieber auf.

  • Übermalen. Einfach das Hintergrundbild neu malen. Das ist das Grundprinzip jedes Computerspiels. Egal ob sich etwas ändert oder nicht, es wird einfach mit einer bestimmten Frequenz (FPS) alles neu gezeichnet, weil Abfragen viel zu lange dauern würden. Beim neuzeichnen musst du natürlich die Reihenfolge beachten. Zuerst wird das gezeichnet was nachher zuunterst sein soll. Also der Hintergrund. Wenn dein Hintergrund die Grafik nicht aufüllen sollte ist es empfehlenswert einfach mit _GDIPlus_GraphicsClear die Grafik komplett in einer Farbe zu färben. Das geht auch wesentlich schneller als ein Bild zu zeichnen. Ich würde dir empfehlen, bevor du mit deinem Spiel so richtig loslegst, erstmal ein bisschen was zu Game-Engines allgemein durchzulesen (nur ganz oberflächlich), dann dich mit GDI+ vertrauter zu machen (ggf. mit Tutorial oder Beispielen), und dann mal ein paar der bereits vorhandenen GDI+ basierten AutoIt Spiele hier im Forum anzuschauen. Davon gibt es einige, mehr oder weniger umfangreich/kompliziert. Ich hab auch ein paar kleinere gemacht, und Marsi hat sogar ein sehr gutes Tower Defense Spiel gemacht (das dürfte für dich relevant sein?).
    Und zu deiner 2ten Frage: Ja, natürlich ist es möglich. Im Grunde ist hier alles möglich, und nur eine Frage des Aufwands. ^^ Wenn du es nicht übertreibst und mehr als 400 Objekte gleichzeitig auf dem Bildschirm rumlaufen lässt, läuft das dann auch flüssig (ansonsten geht da schnell die Framerate in den Keller und es sieht nicht mehr so toll aus). Eine unbestimmte Anzahl von Objekten solltest du immer in Arrays unterbringen und verwalten.

  • Besten, besten, besten dank! Doch ich gebe erlich zu, ich bin nicht so der typ der sich in tausend sachen reinliest um dan erst mit der programmierung anzufangen :D Aber wenn ich das hintergrundbild neu lade, dan sind (Theoretisch gesehen) die Tower, die vom spieler draufgesetzt wurden ja eig. auch mit weg. Die müsste ich dan ja auch wieder neuladen. Nur als beispiel: er hat 3 Tower. Diese sind auf dem spielfeld verteilt. Dan müsste ich ja vorher in einem Array speichern wo die ganzen Tower stehen & welche & die dan auch wieder neuladen.

    Wenn ich das bis hier jz. richtig verstanden habe & dan da ca. 20-30 (oder vieeeeel mehr) monster rum laufen sollen und dan da noch Tower stehen (auch so 15-20) und ich muss nach jedem Gekillten monster die Map wieder neu laden, sicher das es dan nicht anfängt zu hängen? Nicht das ich da jz zuviel hoffnung reinstecke, das es alles so geht wie ich will & es dan nachher doch nicht tut ;(

    MfG Nico

    MfG - Mit freundlichen Grüssen

    die Welt liegt uns zu Füssen, den wir steh'n drauf

    wir geh'n drauf für ein Leben voller Schall und Rauch

    bevor wir fall'n, fall'n wir lieber auf.

  • Zitat

    Die müsste ich dan ja auch wieder neuladen. Nur als beispiel: er hat 3 Tower. Diese sind auf dem spielfeld verteilt. Dan müsste ich ja vorher in einem Array speichern wo die ganzen Tower stehen & welche & die dan auch wieder neuladen.


    Alles musst du jeden Durchgang in der Hauptschleife neuzeichnen ;). Die Koordinaten von allen beweglichen Objekten in einem Array zu speichern ist wohl das einzig sinnvolle, ja ^^. Am besten in einem 2D Array in der Art:

    Code
    Global $aTowers[10][2] = [[9]] ;9 ist die Anzahl der Array Elemente in der ersten Dimension (in diesem Fall Türme)
    $aTowers[1][0] = 220 ;Turm 1 - X Position
    $aTowers[1][1] = 50 ;Turm 1 - Y Position
    $aTowers[2][0] = 10 ;Turm 2 - X Position
    $aTowers[2][1] = 165 ;Turm 2 - Y Position


    Da deine Türme nachher sicherlich noch mehr Eigenschaften haben, als nur die Koordinaten, kannst du die Anzahl der Elemente in der 2ten Dimension (Eigenschaften pro Turm) entsprechend anpassen.

    Zitat

    Wenn ich das bis hier jz. richtig verstanden habe & dan da ca. 20-30 (oder vieeeeel mehr) monster rum laufen sollen und dan da noch Tower stehen (auch so 15-20) und ich muss nach jedem Gekillten monster die Map wieder neu laden, sicher das es dan nicht anfängt zu hängen?


    Garantieren kann ich da nichts, aber wenn du da viel Arbeit reinsteckst, ein paar Tricks benutzt (wie zum Beispiel Marsi oder auch ich mit _WinAPI_BitBlt) und effizient/sauber programmierst, dann sollten diese Zahlen locker drin sein.
    Am Anfang kannst du ja versuchen mal die Basis für dein Spiel fertig zu stellen und nur ein paar Dummy Bilder für Türme etc. einzusetzen. Dann erhöhst du die Anzahl, solange bis das Limit erreicht ist und machst dir dann Gedanken, ob du da noch nachbessern musst.

  • Hi,
    wie schon von name22 gesagt, lies dir durch, was du zu diesem Thema bekommen kannst, ansonsten wird das nix...
    Du hast weder jemals ein grafisches Spiel geschrieben noch irgendeine Ahnung von Grafik-Programmierung, also eigne dir die Vorraussetzungen an und lerne laufen, bevor du rennen willst!

    Zitat

    sicher das es dan nicht anfängt zu hängen? Nicht das ich da jz zuviel hoffnung reinstecke, das es alles so geht wie ich will & es dan nachher doch nicht tut

    Es gibt massig Spiele in AutoIt, die nicht "hängen", obwohl AutoIt alles andere als eine "schnelle" Sprache ist. Das liegt einfach am Knowhow und Skill der Programmierer.

  • Moin, dann melde ich mich auch mal zu Wort :)

    Der Trick ist AutoIt möglichst wenig machen zu lassen und trotzdem bestmögliche Ergebnisse zu erzielen.

    Beispiel

    Ein Turm
    - Der Turm wird irgendwann platziert. (Einmalige Aktion)
    - Nachdem er platziert ist verändert er sich nicht mehr, bis er verbessert/verändert wird. (auch das dauert unter umständen Tausende von Frames. Also im Prinzip eine einmalige aktion
    - Der Turm schießt und muss demnach (weil er ja "unter" dem Schuss ist) bei jedem Frame neu gezeichnet werden.

    Für einmalige Aktionen darf das Programm eine Weile brauchen. (auch nicht sooo lange).
    Für regelmäßig auftretende Aktionen (z.B. Zeichnen des Turms) muss immer für jeden Turm eine Funktion aufgerufen werden.

    Die Kunst ist es jetzt aus regelmäßigen Abläufen einmalige zu machen.

    In dem Fall ist das relativ einfach: Man erzeugt extra für Türme einen neuen Puffer. (Bitmap).
    Jedes Mal, wenn ein Turm gebaut/verändert wird wird genau die Stelle an der der Turm Grafische Veränderungen vornimmt überzeichnet.
    Anschließend muss bei jedem Frame nur der Puffer gezeichnet werden der beliebig viele Türme beinhaltet.

    --> Obwohl man z.B. 50 Türme hat reicht ein einziger BitBlt pro Frame aus um die Türme alle zu zeichnen.

    Besitzen die Türme bewegliche Teile geht das natürlich nicht auf die Art. Dann muss man sich andere Tricks überlegen.
    Man sucht also immer gleichbleibende Gemeinsamkeiten und versucht diese zusammenzufassen.


    Um die "niedere" Rechenarbeit kommt man leider meistens nicht herum. (im Regelfall). d.h. Für 20 Gegner und 20 Türme werden 400 Kollisionskontrollen (incl Listen für alle Gegner in Reichweite die dann nach bestimmten Kriterien sortiert werden müssen) nötig.

    Hier hilft es nur die 2ms in Kauf zu nehmen um alle Positionen der Türme und Gegner (und Reichweiten usw) in Dllstructs zu packen und eine Dll für das Problem zu schreiben. Die ist dann idr in weniger als einer ms ausgeführt.

    Fazit: Wenn du ein "größeres" Spiel programmieren willst brauchst du bei AutoIt einiges an Ahnung, ASM Kenntnisse oder Dll Kenntnisse. Ohne Letztere ist man vorallem bei im Prinzip einfachen aber häufig auftretenden Berechnungen absolut aufgeschmissen.

    Für Minispiele und kleine TDs reicht pures AutoIt aber aus.

    (in meiner Sig: MiniTD = 100% AutoIt. MicroTD = 90% AutoIt 10% ASM)

    lg
    M

  • Okeee, ich mache ein mini mini mini mini mini TD :D die tower müssen sich nicht bewegen & ich werde mich jz erstmal dransetzten alles ans laufen zu bringen (dafuq ?!?! :D)

    Ist es den besser die gesamte Map in Quadraten aufzuteilen um die dan zu übermalen als gleich so ein gesamtes bild zu haben? & ich denke ich fange erstmal klein an und versuche es erstmal damit meinen Gegner übermalt zu bekommen :pp & danach 2 gegner zum laufen zu bringen & mich dan erst mit den Towern befassen.

    DANKE :thumbup:

    MfG Nico

    MfG - Mit freundlichen Grüssen

    die Welt liegt uns zu Füssen, den wir steh'n drauf

    wir geh'n drauf für ein Leben voller Schall und Rauch

    bevor wir fall'n, fall'n wir lieber auf.