|
Antwort |
Registriert seit: 16. Apr 2008 67 Beiträge |
#1
Hallo zusammen,
ich entwickle gerade ein Konzept für ein "kleines" 2D Spiel, was auch im Netzwerk spielbar sein soll. Dazu habe ich ein grundlegendes Problem bzw Frage. Undzwar möchte ich erstmal in einem kleinem Testprojekt realisieren, dass ich eine kleine Figur(Sprich ein gezeichnetes 2D Bild) umherbewegen kann. Bis dahin kein Problem . So nun soll das Netzwerk basiert ablaufen stelle mir das so vor... (Ich will nicht nach Code fragen, sondern nur ob das umsetzbar bzw. komfortabel ist .) Ich habe einen Server und sagen wir mal 3 Clients. Jeder Client hat eine Figur. Diese Figur, von der Klasse TFigur, ist mit Daten wie z.B. die Position der Figur gefüllt. Jetzt sollen automatisch diese Daten zum Server gesendet werden z.B. die Position P(X|Y); Wie läuft das denn normalerweise ab in einem 2D Spiel? Schickt der Server dann die Daten(Positionen) der Figuren der Clients 2-x zum 1. CLient usw. Der Client registriert dann z.B. die Position und zeichnet dann an der Stelle die passende Figur? Oder wie kann man sich das vorstellen?! Wenn ich jetzt z.B. weiß wie das Ablaufen soll wie realisier ich das bzw worüber über TCp oder UDP?! Es soll ja möglichst schnell und komfortabel sein. Hoffe ihr könnt meine Frage verstehen wusste net wie ich es sonst formulieren soll mfg
Christian
|
Zitat |
Registriert seit: 23. Jan 2008 3.686 Beiträge Delphi 2007 Enterprise |
#2
Im groben läuft es ähnlich ab wie du beschrieben hast. Wenn auf einem Client etwas passiert, schickt der dieses Update an den Server, und der wandert seine Client-Liste durch, und schickt jedem ein "Hallo, hier neue Daten für ...". Dazu sollte man sich ein kleines Protokoll ausdenken, wie man welche Infos kenntlich machen will, und in welcher Form sie verschickt werden. Das Senden zum Server macht man dann am besten Event-gesteuert, ggf. mit einer Limitierung auf n Mal pro Sekunde. Daher macht es auch meist eher Sinn absolute, nicht Deltawerte zu schicken, da man sonst schnell Probleme mit asynchronen Clients bekommen kann.
Eine Stufe weiter wäre dann ein Server, der etwas intelligenter ist, in dem er z.B. nicht blind alle Updates an alle Clients schickt, sondern die Spiellogik kennt, und entscheiden kann für welche Clients diese Info überhaupt relevant ist. Ob und wie genau man funktionalen Code auf wen verteilt ist dann nur im konkreten Fall wirklich zu eintscheiden, jedoch dürfte das für dein einfaches Beispiel noch lange nicht relevant werden. Ich persönlich würde zu UDP tendieren, dann allerdings mit einer kleinen eigenen Implementierung eines Acknowledgement-Systems, da ja doch schon mal hier und da ein Päckchen unter geht. Das aber auch nur aus Erfahrungen im LAN, ich weiss nicht, ob im WAN die Latenzen durch das Netz die Geschwindigkeitsvorteile von UDP aufwiegen. (Ich weiss garnicht, ob Router untereinander auch ACKs austauschen.) Der wesentliche Vorteil von TCP ist halt die implizite "Ankommsicherheit" (so denn das Netz selber nicht weg bröselt).
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
|
Zitat |
blackfin
(Gast)
n/a Beiträge |
#3
Jetzt hab ich fast ein Déjà-vu, etwas Ähnliches habe ich ja erst selbst vor ein paar Tagen gefragt
Nach weiterer Recherche im Internet kann ich nun sagen, dass bei einem Spiel an den Server vom Client im Normalfal eigentlich nur folgendes gesendet wird: - Position der Figur bei Bewegungs-Start - Bewegungsrichtung - Bewegungsart (laufen / gehen / drehen etc.) - Bewegungs-Aktion (start / stop) Der Client läuft selbst lokal los und schickt diese Informationen an den Server. Der Server kennt selbst die Geschwindigkeiten der Bewegungsart und ermittelt anhand der Angaben alle paar Sekunden die neue Position der Figur. Dese wird dann ebenfalls alle paar Sekunden an den sendenden Client und die Clients gesendet, die in Sichtweite der Figur sind und mit diesen synchronisiert, dabei hat der Server das Sagen. Hält der Client die Bewegung an, wird ein Bewegungs-Stop an den Server gesendet. Hierbei wird dann final die Position ermittelt und wieder mit dem Client synchronisiert. Beispiel: 1) Client-Figur soll gegen den Uhrzeigersinn nach Norden gedreht werden, der Spieler drückt also z.B. "A". Der Client fängt an, sich lokal (über die Client-seitige Game-Engine) zu drehen und sendet folgendes an den Server: Client => Server: Opcode: START_PLAYER_ROTATION Parameter 1: PLAYER_DIRECTION Parameter 2: ROTATION_CCW ---- 2) Jetzt wird, solange der Spieler "A" gedrückt hält, alle paar Sekunden die Drehrichtung vom Server aus mit den Clients synchronisiert, die in Sichtweite sind (inklusive dem sendenden Client): Server => Clients, die in Sichtweite sind OpCode: PLAYER_ROTATION_SYNC Parameter 1: NEW_PLAYER_DIRECTION ---- 3) Figur ist nach Norden ausgerichtet, der Spieler lässt "A" wieder los. Client => Server: Opcode: STOP_PLAYER_ROTATION Parameter 1: PLAYER_DIRECTION ----- 4) Jetzt wird die finale Drehrichtung vom Server ermittelt und an die relevanten Clients gesendet, die das Objekt (die Figur) dann auf diese Drehrichtung setzen, auch wenn diese von der lokalen abweicht. Server => Clients, die in Sichtweite sind OpCode: PLAYER_ROTATION_SYNC Parameter 1: NEW_PLAYER_DIRECTION ------ Durch diese Verhaltensweise kommt es eben zu den bekannten "Client-Sprüngen", wenn der Server mit dem Client syncronisiert, so dass z.B. die Figur schlagartig eine andere Drehrichtung besitzt. Das gleiche passiert natürlich auch bei Bewegungen. Gerade bei der Drehung von Objekten kann es aber auch durchaus sein, dass hier bei der finalen Postionierung der sendende Client das Sagen hat, da eine Drehung meist in einem so kurzen zeitlichen Rahmen passiert, dass die Synchronisation stottern würde, falls der Server das Sagen hat. Das ist je nach Spiel und Situation selbst festzulegen. Bei Translationen allerdings heisst es eigentlich generell immer: Das, was der Server berechnet hat, gilt. Mein Beispiel bezieht sich jetzt zwar auf die Bewegung in 3D, jedoch gilt das gleiche auch für 2D, nur dass halt hier eine Raumachse wegfällt, ansonsten ist es ja das gleiche Das generell kompilzierte beim Server ist, auf dem Server selbst die Spiel-Logik ohne viel Ballast einzubauen, die auch korrekt die Wegstrecken / Drehungen usw. berechnen kann, ohne dass der Server ja selbst eine Anzeigefläche besitzt und viele Dinge wie z.B. Kollisionserkennung nur "virtuell" enthält, im Gegensatz zum Client, der ja eine Anzeigefläche und "reale" Objekte hat. Dafür werden meist beim Server sogenannte "Maps" generiert, die vorberechnet Daten über die Umgebung beinhalten, auf die schneller zugegriffen werden kann als bei der Live-Prüfung des Clients. Hier wird jedoch meist noch viel auf den Client selbst ausgelagert, die Kollisionsabfragen z.B. sind bei den meisten Spielen immer noch auf der Client-seite, da serverseitig nur ziemlich kompliziert zu berechnen. Dadurch kommt es auch, dass es so viele "Wall-Hacks" für z.B. MMO's gibt. Der Server prüft meist nur in einem recht breiten Rahmen, ob die Client-Anfrage überhaupt gültig ist und korrigiert ggf. zu schnelle Bewegungen oder zu schnelle Schusswiederholraten usw. Als Problem zeigt sich hierbei noch die Paket-Latenz zwischen Client und Server, die kompensiert werden muss. Die Ermittlung, welche Clients bei der Nachrichten-Verteilung relevant sind, wird serverseitig meist mit Client-Gruppen realisiert. Wenn eine Positionsänderung eintritt, ermittelt der Server die Clients in der Nähe und bildet aus diesen eine Client-Gruppe (in Delphi könnte dies z.B. eine TObjectlist sein). Diese wird durch eine Bewegungs-Änderung einer der beinhalteten Clients verändert (Clients hinzugefügt / entfernt). Diese Gruppe bildet dann sozusagen eine "Message-Gruppe" für Events der Clients untereinander, wobei natürlich die Clients nicht direkt zueinander senden können, sondern alles über den Server zwecks Prüfung abgewickelt wird. Die Clients in Sichtweite werden meistens selbst bei einem 3D-Spiel aus Geschwindigkeitsgründen in 2D ermittelt, wobei die Höhenachse ignoriert wird (ausser, diese ist wirklich relevant, z.B. bei einem Weltraum-Game). Somit bleibt einfach die Position der Figur mit einem Sichtradius übrig, bei dem auf Schnittmengen der Clients in der gleichen Zone geprüft wird. Braucht man 3D, dann nimmt man einen Kugel-Radius, statt einem Kreis. Oft wird auch erstmal in 2D ermittelt und bei positiver Schnittmenge noch die 3. Achse geprüft. Diese Prüfung findet aber nur dann statt, wenn sich ein Client in der gleichen Zone bewegt hat oder einer hinzugefügt wird. Optimierungen gibt es hier viele, z.B. die Realisierung von Zonen über virtuelle Octrees oder die Priorisierung und das Gruppieren von Message-Queues / Client-Threads untereinander, die in einer gegeben Zeitspanne innerhalb einer bestimmten Gruppe lagen. (Schlagwort: Spielen als Gruppe in Instanzen oder Ähnliches) Zum Zeichnen der Objekte am Client: Egal ob 2D oder 3D, Objekte werden bei Bewegungsänderungen an sich nicht an der neuen Position "gezeichnet", sondern an eine neue Stelle geschoben (Translation). Natürlich wird dann intern in der Engine neu gezeichnet... Der Server sendet den Clients nach Prüfung auf Sichtweite Events, in denen beim Client ein neues Objekt erzeugt oder eines entfernt werden soll oder ob sich ein Objekt bewegt / verschiebt. Dazu braucht man auf der Client-seite natürlich erstmal einen Bewegungs-Controller, den man mit Befehlen füttern kann (z.B. Nimm Objekt x und bewege es mit Geschwindigkeit y in Richtung z). Doch gibt es generell zwei grundlegend verschiedene Ansatzpunkte, um eine Animations-Engine zu verwirklichen: I) Punkt-/Vertexbasiertes Animieren: Animationen sind dabei Objekt-Intern und sind Punkt-basierend. Animationsüberlagerungen werden dabei meist über Kombinationen der Punkt-Animationen ausgeführt. So kann sich eine Figur z.B. gleichzeitig nach vorne bewegen (Lauf-Animation) und springen (Spring-Animation). Ist man hier im 3D-Raum, so werden über den Bewegungs-Controller die Bewegungen der Knochenpunkte (Bone-Joints) für alle gerade aktiven Animationen addiert und interpoliert. Erklärung hierzu: Eine Spieler-Figur besteht in 3D meist aus dem 3D-objekt selbst (Mesh), dem ein Knochengerüst zugrundeliegt, das die "Verzerrung" des Mesh bei Bewegungen steuert. Bewegt sich ein Knochen, so werden über die Gewichtung der Knochen-Knotenpunkte die Vertices der Mesh-Aussenhaut verschoben . Um eine Animation zu erzeugen, bewegt man also im 3D-Programm die Knochen für jeden Bewegungs-Schritt und erstellt dann eine Liste von Positionen für eine Animation, die man dann von der Game-Engine abrufen kann. Diese interpoliert dann zwischen den Positionen, um eine flüssige Bewegung zu erhalten. Vom Server kommen dann nur noch Befehle ala START_ANIMATION_RUN, springt der Spieler während des Laufens, kommt vom Server START_ANIMATION_JUMP, diese wird der aktiven Laufanimation hinzugefügt, wobei eine Kombination aus Lauf- und Sprunganimation entsteht. Der Vorteil dieser tehcnik liegt auf der Hand: Man muss nur einmal das Objekt modellieren, kann durch Knochenbewegung alle möglichen Animationen zusammenbasteln und kann die einzelnen Animationen beim Anzeigen auch noch überlagern lassen, wodurch eine riesige Anzahl von unterschiedlichen Bewegungen entstehen kann. Für dein Vorhaben, ein Bild zu verschieben, brauchst du das alles aber erstmal gar nicht, da es ja keine Animationen "im" Bild gibt, sondern nur das Bild an sich verschoben wird. Die Erklärung hierzu soll in erster Linie als Ausblick dienen, falls es eben nicht bei einem Verschieben von Bildern bleibt und du eventuell Punkt-vertexbasiert arbeiten willst. Das ist auch bei der Konzipierung zu überlegen, wie man Animationen eben realisieren will. Kommen wir aber zu Animations-Variante 2, die in deinem Fall wohl eher zutrifft: II) Sprite-basiertes Animieren: Eine Sprite-Animation besteht aus umschaltbaren Abfolgen von Einzelbildern und beinhaltet keine Punkte-Verschiebung / Verzerrung am Objekt selbst. Sobald das Bild verschoben / bewegt wird, wird auch die Stand-Animation des Bildes umgeschaltet auf eine Lauf-Animation. Sprich: Kommt vom Server ein BEWEGUNG_START, schaltet das Bild auf eine andere Animations-Reihenfolge um, bei einem BEWEGUNG_STOP wieder zurück auf die Stand-Animation. Dafür brauchst du erstmal eine Sprite-Engine, die dieses Umschalten und animieren handlen kann. (Andorra 2D z.B.) Das Problem beim Sprite-basierenden Animieren ist die Tatsache, dass man für jegliche Bewegungs-Kombination eine eigene Abfolge von Einzelbildern braucht, da man keine Punkte hat, dieman verzerren / verschieben kann und somit Kombinationen von Bewegungen unmöglich sind, ohne eine eigene Animation dafür zu zeichnen. So werden ja auch z.B. herkömmliche Zeichentrickfilme animiert, jedes Bild ist Handarbeit. III) Kombination aus Vertex-basiertem Animieren und Sprites: Natürlich kann man die beiden Techniken auch kombinieren. Man bastelt sich ein Modell in einem 3D-Program mit Knochengerüst und exportiert die einzelnen Animationen als Einzelbilder für die Sprite-Engine. Das ist heutzutage eigentlich der übliche Weg für ein 2D-Spiel. Zu UDP/TCP: UDP wird bei aktuelleren Spielen übers Internet nur noch für relativ "unwichtige" Informationen verwendet, die regelmäßig versendet werden und bei denen es nicht wichtig ist, dass sie wirklich jedesmal richtig ankommen (z.B. Client-/Serverzeit-Sync, Latenz-Ermittlung) und somit auch nicht aufwändig geprüft / verifiziert werden müssen. Für wirklich relevante Dinge wie Bewegungen und der Spiel-Logik allgemein wird allerdings fast immer TCP verwendet, da der zeitliche Overhead der Daten-Strukturierung / Verifizierung bei UDP meist grösser ist als der native Geschwindigkeits-Vorteil gegenüber TCP. Dies gilt, wie gesagt, für Spiele übers Internet, bei LAN kann man, wie Medium bereits sagte, UDP meist ohne grosse Probleme auch dafür verwenden. Modernere MMO's oder auch Shooter benutzen somit meist eine Mischung aus UDP und TCP. UDP für unwichtiges, TCP für wichtiges. Fazit: Lange Rede, kurzer Sinn. Bevor du dir über die Netzwerk-Technik überhaupt Gedanken machen kannst, brauchst du als aller Erstes auf der Client-Seite einen Bewegungs-Koordinator/Controller für Animationen, so dass du vom Server überhaupt Befehle wie ANIMATION_1_START und ANIMATION_1_STOP empfangen und auswerten kannst. Dieser ist entweder Sprite-basierend oder Punkt-vertexbasierend, was eine grundlegende Entscheidungsfrage ist. Diese Animations-Engine kannst du dann erst einmal lokal implementieren und testen. Wenn der Controller funktioniert, kannst du dann auf die Serverlogik gehen und nach obigen Punkten überlegen, was der Server zu prüfen und zu senden hat, damit die Clients immer schön synchron animieren. Ich weiss, das war nun viel Text und hat mit deiner simplen Frage nur noch in Teilen zu tun. Ich hoffe, es nützt dir trotzdem etwas Geändert von blackfin (23. Aug 2010 um 14:09 Uhr) |
Zitat |
Registriert seit: 16. Apr 2008 67 Beiträge |
#4
Erstmal ein dickes Danke und Respekt für die Antworten besonders für den langen Text
Nach meinem ersten Überfliegen denke ich, dass der Text mir helfen wird. Arbeite den erstmal durch und wenn noch Fragen aufkommen, weiß ich ja an wen ich mich wenden muss mfg
Christian
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |