GDI+ Animationen und AutoIt Multiplayer

  • Hey,
    Habe zwei Fragen zu denen ich dringend eine Antwort suche.
    Ich will aktuell ein Game im Stil von Streetfighter oder Tekken erstellen.
    1. Frage, gibt es eine Möglichkeit .gif Animationen mit GDI+ direkt einzubinden, oder muss ich das im AutoIt-Script "animieren"?
    2. Frage, gibt es eine Möglichkeit Multiplayer 1vs1 einzubauen?
    Da hatte ich mir vorgestellt das die Spielerdaten auf einen FTP Server die ganze Zeit hochgeladen werden und vom anderen Spieler ausgelesen werden. Allerdings bin ich mir sicher das dass nicht wirklich effektiv ist oder überhaupt funktioniert, hoffe jemand kann mir da helfen :)
    Mfg

  • Zu 2)
    Das funktioniert wahrscheinlich schon, ist aber wie du schon selbst angemerkt hast nicht sehr effektiv. Ein in AutoIt geschriebener TCP- oder UDP-Server (einfach mal die Funktionen in der Hilfe anschauen) wäre besser und auch einfacher zu verwenden.

  • 1) Ne, Animationen kannst du so direkt nicht einfügen. Musst du wohl oder übel im Script animieren. Kannst aber den aufbau einer *.gif lernen und dann die einzelnen Bilder selber auslesen. Könnte man sicherlich immer wieder gebrauchen.

  • Was man auch machen könnte wäre folgendes: Jede Animation besteht aus einigen (immer gleich vielen) "Phasen" oder eben Einzelbildern, die alle zum Beispiel praktisch in einem Array abgespeichert werden. In der Zeichnen-Methode kann man dann statt dem Index für das Bild, eine Globale Variable "$Phase" einsetzen, welche vom Script in einem vorgegebenen Zeitabstand verändert/hochgezählt wird... Somit hat man bei geschickter Bilderwahl für die einzelnen Phasen, eine schöne 'Animation'.

    LG
    Christoph :)

  • Hmm okey, die erste Frage wäre beantwortet.
    Hab aber grade ein kleines Problem mit den TCP Servern.
    Man schickt ja ein Paket so:

    [autoit]

    $socket = TCPConnect("xxxxxxxx", 5001)
    If $socket = -1 Then
    MsgBox(16, "Error", "Die Verbindung zum Server konnte nicht hergestellt werden!")
    EndIf
    $sendedBytes = TCPSend($socket, "Hi")
    If $sendedBytes = 0 Then
    MsgBox(16, "Error", "Das Paket konnte nicht gesendet werden.")
    EndIf

    [/autoit]


    Und empfangen tut man es so:

    [autoit]


    $mainsocket = TCPListen("xxxxxxxx", 5000)
    $acceptedSocket = TCPAccept($mainsocket)
    If $acceptedSocket <> -1 Then
    $receivedData = TCPRecv($acceptedSocket, 1024)
    MsgBox(64, "Client hat was empfangen!", "Server hat eine Nachricht gesendet: " & $receivedData)
    TCPCloseSocket($acceptedSocket)
    EndIf

    [/autoit]


    Das Problem ist, egal was ich sende, also z.B. eine Bewegungsvariable oder eine Verändernung des Mana etc., alles wird in $receivedData gespeichert.
    Gibt es eine Möglichkeit quasi $sendedBytes = TCPSend($socket, $x) Auch mit $x ? TCPRECV(..) auffangen zu lassen, ohne einen neuen Port aufzumachen?
    Mfg

  • Dann musst du dem Server eben noch die Information senden, was für Daten er überhaupt gerade empfängt und diese dann auswerten. Zum Beispiel TCPSend($Server, "PosX|" & $x) ;)

  • Hmm habs mir schon gedacht, wollts aber eigentlich vermeiden^^ Okey danke.
    Noch ein Problem. Bei den beiden Scripten sollte eigentlich jeweils eines der roten Quadrate bewegbar sein und dies auf die andere GUI übertragen. Ich such jetzt schon 2 Stunden nach dem Fehler, finde ihn aber einfach nicht. Die beiden Quadrate bewegen sich jeweils, allerdings überträgt es die Daten nicht, obwohl es eigentlich funktionieren sollte.
    client.au3:

    Spoiler anzeigen
    [autoit]


    #include <GuiConstants.au3>
    #include <GDIPlus.au3>
    #include <WindowsConstants.au3>
    Opt("GUIOnEventMode", 1)
    OnAutoItExitRegister("_exit")
    _GDIPlus_Startup()

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

    TCPStartup()
    $mainsocket = TCPListen("127.0.0.1", 5000)

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

    HotKeySet("s", "_move")

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

    $gui = GUICreate("Client", 1000, 600)

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

    Global $iWidth = 400, $iHeight = 400
    Global $aPos_Rect[4] = [0, 100, 200, 200]
    Global $aPos_Rect2[4] = [300, 100, 200, 200]

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

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($gui) ;Grafikobjekt
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($gui)
    $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000) ;Pinsel

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

    GUISetOnEvent(-3, "_exit")
    GUIRegisterMsg(0x000F, "WM_PAINT")
    GUISetState(@SW_SHOW)

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

    While 1
    $acceptedSocket = TCPAccept($mainsocket)
    If $acceptedSocket <> -1 Then
    $receivedData = TCPRecv($acceptedSocket, 1024)
    $aPos_Rect[0] = $receivedData
    _WinAPI_RedrawWindow($gui, 0, 0, $RDW_INTERNALPAINT)
    TCPCloseSocket($acceptedSocket)
    EndIf
    WEnd

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

    Func _senden()
    $socket = TCPConnect("127.0.0.1", 5001)
    If $socket = -1 Then
    MsgBox(16, "Error", "Die Verbindung zum Server konnte nicht hergestellt werden!")
    EndIf
    $sendedBytes = TCPSend($socket, $aPos_Rect2[0])
    If $sendedBytes = 0 Then
    MsgBox(16, "Error", "Das Paket konnte nicht gesendet werden.")
    EndIf
    TCPCloseSocket($socket)
    EndFunc

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

    Func _exit()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphic2)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

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

    Func _move()
    $aPos_Rect2[0] += 2
    _WinAPI_RedrawWindow($gui, 0, 0, $RDW_INTERNALPAINT)
    EndFunc

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

    Func WM_PAINT()
    _GDIPlus_GraphicsClear($hGraphic,0xFFF0F0F0)
    _GDIPlus_GraphicsClear($hGraphic2,0xFFF0F0F0)
    _GDIPlus_GraphicsFillRect($hGraphic, $aPos_Rect[0], $aPos_Rect[1], $aPos_Rect[2], $aPos_Rect[3], $hBrush)
    _GDIPlus_GraphicsFillRect($hGraphic2, $aPos_Rect2[0], $aPos_Rect2[1], $aPos_Rect2[2], $aPos_Rect2[3], $hBrush)
    EndFunc

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

    TCPShutdown()

    [/autoit]


    server.au3:

    Spoiler anzeigen
    [autoit]


    #include <GuiConstants.au3>
    #include <GDIPlus.au3>
    #include <WindowsConstants.au3>
    Opt("GUIOnEventMode", 1)
    OnAutoItExitRegister("_exit")
    _GDIPlus_Startup()

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

    TCPStartup()
    $mainsocket = TCPListen("127.0.0.1", 5001)

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

    HotKeySet("w", "_move")

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

    $gui = GUICreate("Server", 1000, 600)

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

    Global $iWidth = 400, $iHeight = 400
    Global $aPos_Rect[4] = [0, 100, 200, 200]
    Global $aPos_Rect2[4] = [300, 100, 200, 200]

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

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($gui) ;Grafikobjekt
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($gui)
    $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000) ;Pinsel

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

    GUISetOnEvent(-3, "_exit")
    GUIRegisterMsg(0x000F, "WM_PAINT")
    GUISetState(@SW_SHOW)

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

    While 1
    $acceptedSocket = TCPAccept($mainsocket)
    If $acceptedSocket <> -1 Then
    $receivedData = TCPRecv($acceptedSocket, 1024)
    $aPos_Rect2[0] = $receivedData
    _WinAPI_RedrawWindow($gui, 0, 0, $RDW_INTERNALPAINT)
    TCPCloseSocket($acceptedSocket)
    EndIf
    WEnd

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

    Func _senden()
    $socket = TCPConnect("127.0.0.1", 5000)
    If $socket = -1 Then
    MsgBox(16, "Error", "Die Verbindung zum Server konnte nicht hergestellt werden!")
    EndIf
    $sendedBytes = TCPSend($socket, $aPos_Rect[0])
    If $sendedBytes = 0 Then
    MsgBox(16, "Error", "Das Paket konnte nicht gesendet werden.")
    EndIf
    TCPCloseSocket($socket)
    EndFunc

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

    Func _exit()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphic2)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

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

    Func _move()
    $aPos_Rect[0] += 2
    _WinAPI_RedrawWindow($gui, 0, 0, $RDW_INTERNALPAINT)
    EndFunc

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

    Func WM_PAINT()
    _GDIPlus_GraphicsClear($hGraphic,0xFFF0F0F0)
    _GDIPlus_GraphicsClear($hGraphic2,0xFFF0F0F0)
    _GDIPlus_GraphicsFillRect($hGraphic, $aPos_Rect[0], $aPos_Rect[1], $aPos_Rect[2], $aPos_Rect[3], $hBrush)
    _GDIPlus_GraphicsFillRect($hGraphic2, $aPos_Rect2[0], $aPos_Rect2[1], $aPos_Rect2[2], $aPos_Rect2[3], $hBrush)
    EndFunc

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

    TCPShutdown()

    [/autoit]
  • Ich habe gerade zwar keine Zeit um den Fehler in deinen Scripts zu suchen, aber bitte missbrauche TCP nicht so! ^^ Wenn du 2 Spieler hast, die über die Position des Anderen bescheid wissen sollen, dann ist immer einer der Server und einer der Client. Dann baut der Client eine Verbindung zum Server auf und über diese Eine Verbindung werden dann alle Pakete verschickt. Hier hatte ich schon mal ein Beispiel dazu gepostet... Und Ja dieses Thema haben wir hier wirklich schon hunderte Male durchgekaut. ;)
    Edit: Ich glaub ich setz mich jetzt wirklich mal an ein gescheites TCP-Tutorial...

    LG
    Christoph :)

    Einmal editiert, zuletzt von BinDannMalWeg (10. Februar 2013 um 13:11)

  • Hab mal wieder ein kleines Problem mit mehreren Clients :/
    Ich habe jetzt einfach mal die UDF von hier genommen: https://autoit.de/index.php?page…2087#post262087
    Damit
    klappt auch alles wunderbar, aber der Client verarbeitet irgendwie die
    Returns nicht. Sleep funktioniert nicht und ich weiß nicht was Christoph mit
    "Normalerweise macht man das so, dass der Client/Server die Pakete
    'unvorbereitet' empfängt." meint.
    Bevor man mein Script liest,
    solltest man vlt wissen worum es geht, ich will wie gesagt ein
    Multiplayerfähiges StreetFighter Game bauen. Aber, weil man sonst die
    Ports freigeben muss, will ich das nicht über einen Host & einen
    Client laufen lassen wie in etwas älteren Spielen, WarCraft III z.B.
    sondern ich will einen großen Server auf dem dann immer zwei Clients
    zusammen spielen können. Aktuell löse ich das so, indem ich bei Login
    einer freien $player[$i] diesen Client zuteile. In der späteren Match
    Funktion soll der Server dann einfach zwei Clients die eingeloggt sind
    zusammenwerfen.
    Server.au3

    Spoiler anzeigen
    [autoit]


    #include "TCPServer.au3" ;http://pastebin.com/Ht8vqAXN
    $Server_IP = "25.57.169.7"
    $Server_Port = 32976
    Global $player[99]
    For $i=0 To 98
    $player[$i] = False
    Next
    Global $login = False
    _TCPServer_RegisterEvent($TCPSERVER_RECEIVEDDATA, "ReceivedData")
    _TCPServer_Startup($Server_IP, $Server_Port)
    ConsoleWrite("Server ist nun hochgefahren." & @CRLF)

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

    While Sleep(100)
    WEnd

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

    Func ReceivedData($socket, $data)
    $data = StringSplit($data, "|")
    Switch $data[1]
    Case "SHUTDOWN"
    ConsoleWrite("Server wird runtergefahren." & @CRLF)
    _TCPServer_Shutdown()
    Exit
    Case "CONNECT"
    If ($data[0] = 2) Then
    For $i=0 To 98
    If $player[$i] = False Then
    $player[$i] = True
    ConsoleWrite("Ein Client hat sich als Player " & $i & " eingeloggt." & @CRLF)
    Return $i
    $login = True
    ExitLoop
    EndIf
    Next
    If $login <> True Then
    Return "Der Server ist aktuell ausgelastet. Versuch es später nochmal."
    ConsoleWrite("Der Server ist ausgelastet." & @CRLF)
    EndIf
    $login = False
    EndIf
    Case "LOGOUT"
    If ($data[0] = 2) Then
    $player[$data[2]] = False
    ConsoleWrite("Client " & $data[2] & " hat sich ausgeloggt." & @CRLF)
    EndIf
    Case Else
    ConsoleWrite("Unbekanntes Kommando: " & $data[1] & @CRLF)
    EndSwitch
    EndFunc

    [/autoit]


    Client.au3

    Spoiler anzeigen
    [autoit]


    #include
    #include
    Opt("GUIOnEventMode", 1)
    TCPStartup()
    $Server_IP = "25.57.169.7"
    $Server_Port = 32976
    $hGUI = GUICreate("GDI-TCP-Client", 400, 400)
    $button1 = GUICtrlCreateButton("Einlogen", 10, 10)
    $button2 = GUICtrlCreateButton("Ausloggen", 10, 60)
    GUISetOnEvent(-3, "_exit")
    GUICtrlSetOnEvent($button1, "_einloggen")
    GUICtrlSetOnEvent($button2, "_ausloggen")
    GUISetState(@SW_SHOW)

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

    $MainSocket = TCPConnect($Server_IP, $Server_Port)
    If @error Then

    MsgBox(16, 'Fehler beim Verbinden', 'Entweder stimmen IP-Adresse/Port
    nicht, oder es ist bereits ein anderer Client mit dem Server
    verbunden.', 10)
    _exit()
    EndIf

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

    While 1
    $Recv = TCPRecv($MainSocket, 1024)
    If @error Then _exit()
    If $Recv <> '' Then
    If StringIsDigit($Recv) Then
    MsgBox(0, "", "Du bist nun Player " & $Recv)
    Global $baum = $Recv
    Else
    MsgBox(0, "", $Recv)
    EndIf
    EndIf
    WEnd

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

    Func _einloggen()
    TCPSend($MainSocket, "CONNECT|")
    EndFunc
    Func _ausloggen()
    TCPSend($MainSocket, "LOGOUT|" & $baum)
    EndFunc

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

    Func _exit()
    TCPCloseSocket($MainSocket)
    TCPShutdown()
    Exit
    EndFunc

    [/autoit]

    Noch anzumerken ist, das dies meine Hamachi IP ist, also nicht wundern das ich sie nicht zensiere^^
    Wäre nett wenn mir jemand helfen könnte,
    Mfg Nakro

  • Auf den ersten Blick finde ich in den Skripten jetzt keinen Fehler...
    Was mich allerdings wundert ist die im Server angegebene IP-Adresse. Sollte da nicht eigentlich sowas wie "127.0.0.1" oder @IPAddress1 stehen? Hast du mal den Rückgabewert von _TCPServer_Startup überprüft? Es könnte ja sein, dass der Server gar nicht startet und der Client somit gar nicht die Möglichkeit hat, irgendwelche Daten zu verarbeiten.

  • Gut, dann poste ich mal wieder hier damit ich keinen neuen Thread aufmachen muss.
    Ich hab grade massive Probleme mit GDI+ und Backbuffern. Klappt alles super bis auf die Imagegröße.
    Die wird irgendwie durch die Bitmap verkleinert, die Werte bleiben aber die gleichen(die ich ja später brauche zum Hitbox berechnen).
    Wenn ich die Bitmap auf die selbe Größe wie die Figur mache, wird sie irgendwann abgeschnitten.

    Mit gleicher Bitmap, Bild ist in der richtigen Größe wie die Variablen aber wird abgeschnitten wenn man zu weit läuft:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>
    #include <WindowsConstants.au3>
    #include <GuiConstants.au3>
    Opt("GUIOnEventMode", 1)
    _GDIPlus_Startup()
    Global $aPos_RectX[2] = [0, 400]
    Global $aPos_RectY[2] = [0, 400]
    Global $aPos_RectW[2] = [100, 100]
    Global $aPos_RectH[2] = [142, 142]
    HotKeySet("w", "_move")

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

    $hGUI = GUICreate("GUI", 700, 700)

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

    $hPlayer = _GDIPlus_ImageLoadFromFile("./data/char1.gif")
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($aPos_RectW[0], $aPos_RectH[0], $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    GUISetOnEvent(-3, "_exit")
    GUIRegisterMsg(0x000F, "WM_PAINT")
    GUISetState(@SW_SHOW)

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

    While 1
    WEnd

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

    Func _exit() ; Beenden des Clients
    _GDIPlus_ImageDispose($hPlayer)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    Exit
    EndFunc
    Func WM_PAINT() ; Redraw Funktion
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFF000000 + 0xF0F0F0)

    _GDIPlus_GraphicsDrawImageRect($hBackbuffer,$hPlayer, $aPos_RectX[0], $aPos_RectY[0], $aPos_RectW[0], $aPos_RectH[0])

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

    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $aPos_RectX[0], $aPos_RectY[0], $aPos_RectW[0], $aPos_RectH[0])
    EndFunc
    Func _move()
    $speed = 1
    $aPos_RectX[0] += $speed
    _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT)
    EndFunc

    [/autoit]

    Mit Bitmap die so groß ist wie die GUI, Bild wird verkleinert Height und Width Werte bleiben aber normal groß:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>
    #include <WindowsConstants.au3>
    #include <GuiConstants.au3>
    Opt("GUIOnEventMode", 1)
    _GDIPlus_Startup()
    Global $aPos_RectX[2] = [0, 400]
    Global $aPos_RectY[2] = [0, 400]
    Global $aPos_RectW[2] = [100, 100]
    Global $aPos_RectH[2] = [142, 142]
    HotKeySet("w", "_move")

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

    $hGUI = GUICreate("GUI", 700, 700)

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

    $hPlayer = _GDIPlus_ImageLoadFromFile("./data/char1.gif")
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(700, 700, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    GUISetOnEvent(-3, "_exit")
    GUIRegisterMsg(0x000F, "WM_PAINT")
    GUISetState(@SW_SHOW)

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

    While 1
    WEnd

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

    Func _exit() ; Beenden des Clients
    _GDIPlus_ImageDispose($hPlayer)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    Exit
    EndFunc
    Func WM_PAINT() ; Redraw Funktion
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFF000000 + 0xF0F0F0)

    _GDIPlus_GraphicsDrawImageRect($hBackbuffer,$hPlayer, $aPos_RectX[0], $aPos_RectY[0], $aPos_RectW[0], $aPos_RectH[0])

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

    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $aPos_RectX[0], $aPos_RectY[0], $aPos_RectW[0], $aPos_RectH[0])
    EndFunc
    Func _move()
    $speed = 1
    $aPos_RectX[0] += $speed
    _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT)
    EndFunc

    [/autoit]