39dll: Verbindung und Kommunikation

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • 39dll: Verbindung und Kommunikation

      Ihr wisst bestimmt, dass man mit der 39dll Multiplayerspiele machen kann. Doch wie geht das eigentlich genau?

      Ganz am Anfang müsst ihr die Scripts über "Scripts" --> "Import Scripts" --> "DllScripts.gml" laden. Jetzt macht ihr am besten ein Objekt, das im Game Start - Event die dll initialisiert:

      GML-Quellcode

      1. dllinit(0, true, false);


      Hier ist das Argument0 der Dateinamen der dll. Ist dieser auf 0, wird automatisch die "39dll.dll" gewählt. Wenn man die dll aber umbenannt hat (z.B. in "beispiel.dll"), so muss man als Argument0 "beispiel.dll" schreiben. Das Argument1 stellt ein, ob die Socket-Funktionen genutzt werden sollen, oder nicht und das Dritte (Argument2), um die Utility-Scripts zu gebrauchen.

      Natürlich müsst ihr dazu die 39dll.dll im selben Ordner, wie die gm6 -, gmk - oder exe - Datei haben!

      Die Grundlagen stehen jetzt! Nun muss die Verbindung her. Diese erstellt man, indem ein Spieler das Spiel created (also erstellt) und der Andere / die Anderen das erstellte Spiel joinen (also mitspielen).

      Dazu macht ihr ein Create - und ein Join - Objekt, welche ein Sprite mit dem "Create" und "Join" Button haben. In den Create-Button kommt in den Left Pressed - Event

      GML-Quellcode

      1. global.master=true;
      2. room_goto(room_warten);


      und in den Join-Button

      GML-Quellcode

      1. global.master=false;
      2. server=tcpconnect(get_string("IP Adresse?","127.0.0.1"),14804,true);
      3. if(server<=0)
      4. {
      5. show_message("Fehler!");
      6. exit;
      7. }
      8. else
      9. {
      10. global.otherplayer=server
      11. room_goto(room_game);
      12. }
      Alles anzeigen


      Zur erklärung:
      Die Variable global.master ist sozusagen der Chef des Spiels. Wenn diese auf true steht, dann ist man der Leiter des Spiels. Diese Variable benützt man, um die Player zu unterscheiden. So kann man zum Beispiel sagen, dass der global.master das Spiel beginnt usw.
      Im Join-Button wird auch zuerst global.master definiert. Danach wird die IP-Adresse des Creators abgefragt, damit man das von ihm erstellte Spiel joinen kann. Hier ist "127.0.0.1" schon eingestellt, weil man sich damit mit sich selber verbindet (Um das Spiel zu testen). Nun wird noch abgefragt, ob der Creator schon created hat bzw schon im Warteraum ist. Wenn ja kommen beide Spieler in den Spielraum.

      Jedoch muss im Warteraum auch noch einen Code hin! Erstelle dazu ein obj_warten mit folgendem Code im Create-Event:

      GML-Quellcode

      1. listen = tcplisten(14804, 2, true);
      2. if(listen <= 0)
      3. {
      4. show_message("Fehler!");
      5. game_end();
      6. }


      und dem hier im Step-Event:

      GML-Quellcode

      1. client = tcpaccept(listen, true);
      2. if(client <= 0) exit;
      3. global.otherplayer = client;
      4. room_goto(room_game);


      Das Create -, das Join - und das dllinit-Objekt kommen nun in einen Raum (z.B. room_verbindung), während das obj_warten in den room_warten kommt.

      Zum Test wird auch ein room_game gebraucht!


      So! Das Erste wäre mal geschafft: Die Verbindung steht!
      Nun müssen die Spieler aber miteinander kommunizieren können (d.h. Variablen miteinander austauschen).

      Zuerst mal die Grundlagen:
      Es gibt zum Senden der Variablen diese Befehle (In diesem Beispiel im Keyboard Right - Event des obj_spieler):

      GML-Quellcode

      1. x+=2
      2. clearbuffer()
      3. writebyte(0)
      4. writeshort(x)
      5. sendmessage(global.otherplayer)
      6. clearbuffer()
      7. writebyte(1)
      8. writestring(global.spielername)
      9. sendmessage(global.otherplayer)
      Alles anzeigen


      Und zum Empfangen diese hier (Kommt in den Step - Event des obj_control):

      GML-Quellcode

      1. var size;
      2. while(true)
      3. {
      4. size = receivemessage(global.otherplayer);
      5. if(size < 0) break;
      6. if(size == 0)
      7. {
      8. show_message("Dein Mitspieler hat das Spiel verlassen!");
      9. game_end();
      10. exit;
      11. }
      12. messageid = readbyte();
      13. switch(messageid)
      14. {
      15. case 0:
      16. newx = readshort()
      17. obj_gegner.x = newx
      18. break;
      19. case 1:
      20. global.gegnername = readstring()
      21. break;
      22. }
      23. };
      Alles anzeigen


      Sieht vielleicht schwer aus, ist es aber nicht!

      Im ersten Code wird die Variable x des obj_spieler mit dem Drücken der rechten Pfeiltaste um 2 erhöht und gleich danach wird der neue Wert der Variable x an den Gegner übertragen.
      clearbuffer() löscht den Buffer (muss immer vorhanden sein!)
      writebyte(0) sagt, mit welcher Variable das Ganze gesendet/empfangen werden soll. Ist diese 0, muss sie beim Empfangen der Variable auch 0 sein. Sie ist sozusagen die Kennungsvariable, damit wenn zwei Variablen gleichzeitig gesendet werden, nicht beide als x-Variable gesehen werden.
      writeshort(x) sendet die Variable x. Wenn man aber einen String senden will, muss man writestring(...) schreiben (in diesem Beispiel writestring(global.spielername))!
      sendmessage(global.otherplayer) sendet diese Nachricht dem Gegner.

      Im zweiten Code, also im Empfang wird zuerst abgecheckt, ob der Gegner noch da ist. Wenn nein wird eine Nachricht angezeigt, dass der Mitspieler das Spiel verlassen hat. Wenn dies jedoch nicht der Fall ist, wird die messageid auf readbyte(); eingestellt. Nun kommen also wieder diese Kenungs-Variablen zum Zuge.
      "case 0:" fragt ab, ob diese Variable 0 ist. Wenn ja wird die Variable newx auf die gelesene Variable (also die gesendete x-Position des Gegners) gestellt, wobei readshort() Variablen und readstring() Strings liest!
      Nun bekommt das Gegner-Objekt (obj_gegner) diese Empfangene Variable als x-Wert zgeteilt.


      So kann man also Variablen miteinander austauschen. Hier muss, wie gesagt immer beachtet werden, dass die Kennungs-Variablen miteinander übereinstimmen!


      Um eine bessere Verbindung zu ermöglichen, sollte man noch ein obj_setnagle mit folgendem Code im Create - Event erstellen:

      GML-Quellcode

      1. setnagle(global.otherplayer,true);


      Hier muss als Argument0 die ID des Sockets haben, den du beschleunigen willst. Argument1 stellt dann ein, ob er beschleunigt werden soll, oder nicht.


      Um die dll wieder zu entladen sollte man in einem Objekt im Game End - Event noch den Code

      GML-Quellcode

      1. dllfree();


      einfügen. Sonst werden noch kleine Dateien auf dem PC gespeichert, was allerdings nicht schlimm ist.


      Ich habe hier ein sehr kleines Example in Form eines Chats gemacht, damit ihr das Ganze noch praktisch sehen könnt! Zum Downloaden HIER klicken!


      Ich hoffe, das Tutorial hat euch geholfen! Bei Fragen bitte hier reinschreiben.
      MfG flogy

      Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von flogy ()

    • Nicht schlecht das Tutorial. Nur finde ich es ähnelt sehr dem 39dll Tutorial von Toon-Master. Vielleicht könntest du es noch etwas ausbauen, beispielsweise die Argumente bei der Initialisierung der DLL nennen.

      -gn
      Kaldor - Das erste echte MMORTS
    • Klar ist er nicht komplett, man braucht ja für ein Game (meistens) noch mehr message IDs. Wenn du nur mid0 brauchst, mache einfach eine geschwungene Klammer unten hin.

      -gn
      Kaldor - Das erste echte MMORTS
    • @ GamerNet: hab mal hingeschrieben, was die einzelnen argumente bewirken. jedoch habe ich diese noch nie gebraucht und weiss deshalb auch nicht wirklich, was man alles damit machen kann :( habe deshalb einfach die übersetzung hingeschrieben...
      dass es dem tut von toon-master ähnelt ist schon möglich. jedenfalls habe ich sein tutorial nicht übersetzt oder benötigt, um dieses hier zu schreiben :)

      @ copyboy: ja, der code war unvollständig! habe die zwei geschwungenen klammern noch dazugefügt! danke für den hinweis.


      mfg flogy
    • Nices Tut, bin oft mit Toon-Master im MSN, er wird wohl noch n tut schreiben, da sein erstes ihm nich gefallen hat ^^;

      Zum glück gibts jetzt auch n deutsches Tut das fürn anfang recht gut is!

      Wäre auch nett wenn du n ganz simplex example machen würdest, damit die leute was zum angucken haben :)
    • Also chatten sollte doch mit dem Gelernten und dem mitgelieferten 39dll Tutorial kein Problem sein:
      Senden von Text:

      GML-Quellcode

      1. chattext = keyboard_string
      2. clearbuffer()
      3. writebyte(3)
      4. writestring(chattext)
      5. sendmessage(global.otherplayer)
      6. keyboard_string = ""

      Empfangen von Text:
      obj_control - Step event (im switch)

      GML-Quellcode

      1. case 3:
      2. chattext2 = readstring()


      -gn
      Kaldor - Das erste echte MMORTS
    • doch nicht das chatten an sich, ich meinte alles zusammen ^^

      EDIT:
      BITTE LESEN!
      nur ein ganz kleiner fehler bei dem code, wo du schon einen fehler hattest:
      hinter der letzten geschweiften klammer kommt kein ";" :D
      Wenns geändert wurde mach ich das hier wieder weg (sonst spam ^^)

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von copyboy ()

    • ich hab mit nem example angefnagen und werde dieses morgen oder übermorgen fertigmachen (chat und pong)!
      wegen dem zusteigen machst du einfach einer, der das spiel created und die anderen joinen dann einfach alle! der creator ist dann der "global.master" und sendet allen mitspielern die koords der objekte, während die mitspieler ihm die koords ihrer spielerobjekte senden!

      mfg flogy
    • @Copyboy: Klar können Spieler während des Games einsteigen. Dabei wird einfach eine neue Message-ID mit zB. dem Nicknamen des neuen Spielers an den Server gesendet. Der dazugehörige Code könnte folgendermaßen aussehen:

      GML-Quellcode

      1. global.name = get_string("Dein Name","");
      2. clearbuffer();
      3. writebyte(3); // Eine neue MID
      4. writestring(global.name, true);
      5. sendmessage(tcpsocket); // bzw. client
      6. var i;
      7. for(i=0;i<maxplayer; i+=1) {
      8. spieler[i] = -1;
      9. i = instance_create(0,0,obj_anderer_spieler);


      -gn
      Kaldor - Das erste echte MMORTS
    • na toll, und wo kommt das hin? ich bin voll der noob im umgang mit den 39dll funktionen, deshalb hab ich ja um ein CHAT Exapmple gefragt, weil das so ziemlich alles beinhaltet, um daraus zu lernen und ein Online Spiel zu machen. kann sein, dass das sich jetzt blöd angehört hat, aber ich kann nichts mit einzelnen Codes anfangen wenn ich nicht dass habe, was um den code herum aufgebaut wurde

      also hier ein paar verbesserungsvorschläge für den chat:
      - Mehr Spieler (wenn möglich unbegrenzt)
      - Ping funktion
      - Nachrichten wenn jemand einsteigt / aussteigt
      - Ping out (wenn jemand nichtmehr "antwortet")
      - Was halt so zu einem "anständigem" Chat gehört ^^

      Fragen:
      - Gibt es sowas ähnliches wie die "mplay_data_"-Funktionen? Ich könnte das ganze auch über den Host abfragen, aber es kann ja sein, dass er dann bei all den abfragen zusammenbringt ^^. Also gibt es solche Funktionen?
      - Was bedeuten eigentlich die Funktionen? Was ist ein Socket? Ich hab das noch garnicht recht begriffen

      @ GN direkt: du bist ja hier im Thread ganz gerne unterwegs, deshalb bitte ich dich: schau bei mir mal in ICQ vorbei ;)
    • also hier ein paar verbesserungsvorschläge für den chat:
      - Mehr Spieler (wenn möglich unbegrenzt)
      - Ping funktion
      - Nachrichten wenn jemand einsteigt / aussteigt
      - Ping out (wenn jemand nichtmehr "antwortet")
      - Was halt so zu einem "anständigem" Chat gehört ^^


      Das sollte ja auch nur ein Beispielprogramm sein, um zu zeigen, wie man Variablen austauschen kann (oder in diesem Beispiel eben Strings)! Es ist total unfertig, aber es reicht, um zu sehen, wie das Ganze aufgebaut ist, denn es ist schliesslich ein 39dll Tutorial und kein "Wie mache ich einen Chat" Tutorial...

      Zu deinen Fragen:
      Welche Funktionen verstehst du nicht? Google doch mal nach der Definition eines Sockets (also "define:socket" eingeben):

      eine Verbindung zwischen einem Programm auf einem Computer über das Internet oder Intranet zu einem anderen Programm auf einem anderen Computer. Der Name kommt vom englischen Wort für Steckdose.


      Software-Schnittstelle zur "Interprozeß-Kommunikation" (IPC). Sockets sind die vollduplexfähige Alternative zu Pipes und Fifos oder auch zu "Shared Memory". Über TCP/IP sind Sockets zB auch im Netzwerk - inklusive Internet - vertreten: Verschiedene Sockettypen arbeiten mit verschiedenen Adressfamilien und bedingen die verschiedenen Netzwerkprotokolle.



      PS: Kann jetzt eine Weile nicht mehr antworten, da ich eine Woche verreise!

      MfG flogy

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von flogy ()

    • naja. mplay_data_ funktionen geben ja eigentlich auch nur werte aus.

      Die 39dll kann das genauso simpel...doch halt viel schneller.

      Man versendet halt infos mit:

      writebyte()
      writestring()
      writeshort() usw

      das is im grunde genau dasselbe.

      Auf der seite des anderen spielers muss die info nur ausgewertet werden.
    • Original von BlaXun
      writebyte()
      writestring()
      writeshort()

      das hab ich ja schon längst verstanden, ich möchte aber MEHRERE Spieler machen (nicht 2). ich sagte ja, ich bin noch ein neuling, aber wie z.B. diese listening - ports oder ähnliches ... ich versteh einfach nicht was die bewirken (is halt anders, wie mplay_init_tcpip)
    • @Copyboy:
      Vielleicht hilft dir das hier weiter. Ist aber nicht von mir - Habe keine Ahnung, wer das gemacht hat. (Gefunden in der GMC)
      -gn
      Dateien
      • MMO-Example.zip

        (25,54 kB, 884 mal heruntergeladen, zuletzt: )
      Kaldor - Das erste echte MMORTS