Sharpex2D 1.3.0 | 2D Game Framework

    • Beta
    • Open Source

    Es gibt 388 Antworten in diesem Thema. Der letzte Beitrag () ist von 3Angle.

      Ich arbeite derzeit am Netzwerkcode und habe mir folgendes überlegt:

      Über die Klasse NetworkSession kann man eine Art Lobby hosten oder joinen. Der Host kümmert sich um die Verbindungseingänge/abbrüche und validiert die Verfügbarkeits der Clients. Das ganze System baut auf Udp auf um schnelle Übermittelungen zu garantieren.

      Hier mal ein Host mit 16 Verbindungen die alle, aller 16 ms (60Fps) 100 Bytes Daten an alle Clients senden (Broadcast):



      Die NetworkSession an sich habe ich bereits mit 100 gleichzeitigen Verbindungen getestet, dabei wird auf dem Server eine Bandwidth von knapp 400bytes/s gebraucht (200bytes/s IO). Der einzelne Client verbraucht dabei gerade mal 2bytes/s IO pro Sekunde. Die Lobby ist also recht performant und hat nur wenig Overhead für die Verwaltung.

      Hier mal ein Beispiel wie es aktuell funktioniert. (Das kann sich natürlich im Release von Sharpex2D 2.x.x noch ändern)

      C#-Quellcode

      1. var hostSession = new NetworkSession();
      2. hostSession.Host(21213);
      3. var session1 = new NetworkSession();
      4. session1.Join(ip, 21213);
      5. session1.Send(new byte[] {5, 5, 7}, null, SessionSendFlags.SendHostOnly);
      6. session1.Send(new byte[] {5, 5, 7}, null, SessionSendFlags.Broadcast);
      7. session1.Send(new byte[] {5, 5, 7}, session1.SessionMembers[0], SessionSendFlags.None);


      Jede gejointe Session erhält vom Host eine Übersicht von allen Verbindungen und kann dann über die Eigenschaft Session.SessionMembers auf diese zugreifen.



      Auf dieser Grundlage kann dann euer eigenes Protocol für euer Spiel aufgesetzt werden, da ihr einfach mit anderen Clients und dem Host kommunizieren könnt. Was haltet ihr davon? Momentan arbeite ich noch an den Feinarbeiten, aber die ersten Tests funktionieren schon ausgezeichnet.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ThuCommix“ ()

      Was ist als höchst nützrlich empfinden würde, wäre etwas das einem das Timing abnimmt. Finde das immer extrem beschissen, wenn man sich darum kümmern muss, dass es überall gleich aussieht, der andere das aber früher oder später bekommt usw.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Hallo Leute,

      lange Zeit kam nichts von mir jedoch war ich nicht untätig. Ich habe weiter an meiner Netzwerkengine gearbeitet und würde behaupten das ich so langsam zufrieden bin.

      Ich habe eine Möglichkeit hinzugefügt mit der Ihr eure Objekte über das Netzwerk synchronisieren könnt, und das ohne Aufwand auf eurer Seite.



      Eure Klasse lasst ihr von INetworkSynchronization erben fügt sie den NetworkSynchronizationManager hinzu und ruft immer PropertyChanged in eurer Klasse auf falls sich eine Property geändert hat.

      Code

      C#-Quellcode

      1. public class Player : INetworkSynchronization
      2. {
      3. private Vector2 _position;
      4. public Vector2 Position
      5. {
      6. set
      7. {
      8. _position = value;
      9. if (PropertyChanged != null)
      10. {
      11. PropertyChanged(this, EventArgs.Empty);
      12. }
      13. }
      14. get { return _position; }
      15. }
      16. public Player()
      17. {
      18. _position = new Vector2(0, 0);
      19. }
      20. public void OnNetworkSynchronize(PacketContext context)
      21. {
      22. var x = _position.X;
      23. var y = _position.Y;
      24. context.Serialize(ref x);
      25. context.Serialize(ref y);
      26. _position = new Vector2(x, y);
      27. }
      28. public short Identifer { get { return 7; } }
      29. public event EventHandler<EventArgs> PropertyChanged;
      30. }



      Identifer ist die _eindeutige_ Nummer die dieses Objekt kennzeichnet. Falls das Objekt sich synchronisieren muss, wird OnNetworkSynchronize aufgerufen, dort serialisiert ihr eure Eigenschaft in einen PacketContext, dieser entscheidet dann automatisch ob gelesen oder geschrieben werden soll. Ob gelesen oder geschrieben werden muss, kommt darauf an, wem das Objekt gehört. Ein Objekt gehört demjenigen der zuerst beim Host den jeweiligen Identifer registiert. Der Server ignoriert ab dann falls eine Änderung des Objekts nicht vom Besitzer aus geht.

      Code

      C#-Quellcode

      1. var host = new NetworkSession();
      2. host.Host(46736);
      3. var playerOnHostSite = new Player();
      4. var playerOnClientSite = new Player();
      5. var client = new NetworkSession();
      6. client.Join(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 46736));
      7. Thread.Sleep(1000);
      8. var clientSyncManager = new NetworkSynchronizationManager(client);
      9. var hostSyncManager = new NetworkSynchronizationManager(host);
      10. hostSyncManager.Attach(playerOnHostSite); // Dem Host gehört das objekt, da es dort zuerst registriert wurde
      11. clientSyncManager.Attach(playerOnClientSite);
      12. playerOnHostSite.Position = new Vector2(28, 19);
      13. Thread.Sleep(1000);
      14. Console.WriteLine(playerOnClientSite.Position); //28, 19 playerOnClientSite wurde von playerOnHostSite synchronisiert
      15. //now the client trys to change the object
      16. playerOnClientSite.Position = new Vector2(32, 238); //der client ist nicht der besitzer
      17. Thread.Sleep(1000);
      18. Console.WriteLine(playerOnHostSite.Position); //28, 19 Der server hat die änderung verworfen da der client nicht der besitzer war
      19. Console.ReadLine();



      Was haltet ihr davon? Natürlich muss man das System nicht verwenden, man kann immer noch sein eigenes Protokoll über die NetworkSession aufsetzen und Rohdaten hin und her schicken.


      @thefiloe

      Halte ich für eine schlechte Idee da alle Spieler laggen würden wenn einer laggt.
      Hey @ThuCommix, arbeitest du noch an der Engine?
      Würde sie gerne verwenden, weiß aber nicht welche Version Networking unterstützt.

      Grüße, Splitty
      Hey @SplittyDev

      Liegt alles fast fertig hier auf der Platte (v2.0.1).. Bin jedoch noch etwas unglücklich mit der Content pipeline und müsste eine extra Anwendung erstellen welche Texturen, SpriteFonts etc erstellt. Darans haberts aber aktuell...
      Wenn ich mich recht erinnere, geht das über das RenderTarget und dem ​GameWindow. Dort gibt es eine entsprechende Property ​SurfaceStyle, wo Du das angeben kannst.
      Dieses Window musst Du halt über SGL.QueryComponent<RenderTarget>().Window holen.

      Grüße
      #define for for(int z=0;z<2;++z)for // Have fun!
      Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

      Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

      Hallöchen,

      ich bin gerade dabei die Content Compiler zu schreiben und damit einhergehend auch das neue Fontsystem. Ab sofort werden Texte in Sharpex2D (< 2.0.0) über SpriteFonts realisiert.

      Vorteile:
      • Fonts müssen auf den Zielcomputer nicht vorhanden sein
      • Schnelligkeit da nun nur noch Texturen gerendert werden müssen
      • Leicht einstellbar
      Eine SpriteFont Datei sieht so aus (ähnlich wie bei XNA):

      SpriteFont1.font

      Quellcode

      1. <?xml version="1.0" encoding="utf-8" ?>
      2. <!--
      3. This file contains an xml description of a font, and will be read by the Sharpex2D
      4. Content Pipeline. Follow the comments to customize the appearance
      5. of the font in your game, and to change the characters which are available to draw
      6. with.
      7. -->
      8. <FontLayout>
      9. <!--
      10. Modify this string to change the font that will be imported.
      11. -->
      12. <FontName>Segoe UI</FontName>
      13. <!--
      14. Size is a float value, measured in points. Modify this value to change
      15. the size of the font.
      16. -->
      17. <Size>14</Size>
      18. <!--
      19. Spacing is a float value, measured in pixels. Modify this value to change
      20. the amount of spacing in between characters.
      21. -->
      22. <Spacing>0.2</Spacing>
      23. <!--
      24. Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
      25. and "Bold, Italic", and are case sensitive.
      26. -->
      27. <Style>Regular</Style>
      28. <!--
      29. Indicates if the sprite font uses kerning for character measurement.
      30. -->
      31. <UseKerning>True</UseKerning>
      32. <!--
      33. CharacterRegions control what letters are available in the font. Every
      34. character from Start to End will be built and made available for drawing. The
      35. default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
      36. character set. The characters are ordered according to the Unicode standard.
      37. -->
      38. <CharacterRegions>
      39. <CharacterRegion>
      40. <Start>32</Start>
      41. <End>126</End>
      42. </CharacterRegion>
      43. </CharacterRegions>
      44. </FontLayout>


      Aus dieser XML kompiliert dann der Content Compiler die fertige SpriteFont. Diese ist so aufgebaut:

      Quellcode

      1. Name
      2. Size
      3. Style
      4. Spacing
      5. Kerning
      6. DataOffset
      7. CharLayout
      8. .
      9. .
      10. .
      11. ImageData


      Den neuen Content Compiler lässt sich über den Postbuild einstellen, und spiegelt euren Content Ordner (Einstellbar) und kompiliert bekannte Dateien (Texturen, Sounds und SpriteFonts)



      Das neue Fontsystem hat noch mehr Vorteile. Texte lassen sich nun formatieren und mit Transparenz darstellen.

      Beispiele

      1.) TextFormat.WordWrap



      2.) TextFormat.Wrap



      3.) TextFormat.None




      Ansonsten ist zusagen das Sharpex2D 2.x.x nicht mehr viel im Weg steht.
      • Restlichen Compiler bauen
      • OpenAL überarbeiten (Ist auch der Grund weswegen ich noch nicht so CSCore commited habe)
      • Direct2D statt DirectX9, (o. DirectX12)
      • Überarbeitung der Initialisierung von SGL
      Hört sich schön an. Freue mich darauf.

      Hast du ein Demo-Projekt, das auf allen Plattformen läuft, für das die Engine konzipiert ist (mit zusätzlichen Optionen für Controller und so)?
      Von meinem iPhone gesendet
      Mit allen Plattformen muss ich dich wohl enttäuschen, ich benutze zu viele APIs von Windows. Bezüglich des Controllers, was brauchst du da?

      Über Gamepad.GetState(PlayerIndex) bekommst du den GamepadState, danach kannst du alle Buttons und Trigger auslesen.



      Achja


      Es wird dann auch für alles entsprechende Templates geben damit man sich nicht selbst abquälen muss.


      Ich kenne mich mit Farseer nicht aus, keine Ahnung in wie fern man da Kompatibilität gewährleisten muss. Durch das neue Font Rendering lassen sich nun auch Transformationen anwenden.



      Ansonsten lassen sich nun auch mp3, und wav Dateien durch den Content Compiler importieren, zur hilfe eilt mir dabei NAudio. Der Content Compiler ist nun soweit fertig (wird nur für Texturen, Sounds und SpriteFonts benötigt) jetzt gilt es bestehendes zu überarbeiten und zu verbessern.
      Das heißt vmtl. eher, dass er für das Beispiel das nicht optimal konfiguriert hat...

      Grüße
      #define for for(int z=0;z<2;++z)for // Have fun!
      Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

      Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: