Netzcode UDP

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Firstdeathmaker

Betreff: Netzcode UDP

BeitragFr, Aug 26, 2005 21:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

da ich nirgens hier im Forum einen guten Code für ein Netzwerkshooter gefunden habe, wollte ich mal Fragen wie man den Netzcode denn am besten realisiert. Ich habe in der Vergangenheit immer wieder etwas damit rumexperementiert, Chat´s sind auch kein Problem, aber mir fehlt es an einer gewissen Strukturiertheit für größere Sachen, wenn man z.B. in einem Shooter die ganzen Gegnerveränderungen, Schüsse e.t.c. verschicken soll.

Wie würdet ihr das angehen, oder habt ihr zufällig einen gescheiten Beispielcode zur Hand?
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Mathias-Kwiatkowski

BeitragSa, Aug 27, 2005 2:05
Antworten mit Zitat
Benutzer-Profile anzeigen
vieleicht währe es dort besser die befehle auf blatt papier zu docomentieren, die man benötigt, und damit du die strucktur nicht verlierst alles vieleicht globalisieren und in einer procedure packen!

vieleicht hilft es dir, und hoffe das ich nicht zu grossen müll gelabert habe!

Firstdeathmaker

BeitragSa, Aug 27, 2005 23:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, das ist mir jetzt keine so große Hilfe, ich habe bisher so gearbeitet, dass ich eine Funktion Clientcommands() geschrieben habe, die alle Befehle ausführt die vom Server komman:

BlitzBasic: [AUSKLAPPEN]
;Clientcommands (Lauscher)
;SC_

Function Clientcommands()
;Anfang der Schleife
Repeat
sc_ip=0
sc_ip=RecvUDPMsg(NET_RECEIVE_STREAM);Wenn ein Befehl ankommt
sc_port=UDPMsgPort(NET_SEND_STREAM)

If sc_ip<>0;Wenn ein Befehl ankommt

Select ReadByte(NET_RECEIVE_STREAM)

Case 0

Case 1;Ping
WriteByte NET_SEND_STREAM,1
SendUDPMsg NET_SEND_STREAM,IP,sc_port-1

Case 2;Serverantwort auf Serversuche
;Erstelle einen Schalter in der Serverliste
clientcommands_zs_gamename$=ReadLine (NET_RECEIVE_STREAM)
clientcommands_zs_serverversion$=ReadLine (NET_RECEIVE_STREAM)
SCH_CREATE(sc_ip,clientcommands_zs_gamename+\" Version \"+clientcommands_zs_serverversion,SYS_GFX_X/2,100+CONNECTMENUE_entrycounter*100,\"GFX\Menü\Mainmenu\options1.png\",\"GFX\Menü\Mainmenu\options2.png\",\"\",\"\",2,1)
CONNECTMENUE_entrycounter=CONNECTMENUE_entrycounter+1

Case 3;Spielinformationen bekommen
NET_SERVER_IP=sc_ip
SCH_DELETE(\"\",1)
SCH_DELETE(\"\",2)
OPTION_SERVER_NAME=ReadLine (NET_RECEIVE_STREAM)
NET_SERVER_VERSION=ReadLine (NET_RECEIVE_STREAM)
OPTION_GAMESPEED#=ReadFloat (NET_RECEIVE_STREAM)


OPTION_startenergie=ReadLine (NET_RECEIVE_STREAM)
OPTION_startcredits=ReadLine (NET_RECEIVE_STREAM)
OPTION_startknowhow=ReadLine (NET_RECEIVE_STREAM)
OPTION_univ_max_x=ReadLine (NET_RECEIVE_STREAM)
OPTION_univ_max_y=ReadLine (NET_RECEIVE_STREAM)
OPTION_planet_min_r=ReadLine (NET_RECEIVE_STREAM)
OPTION_planet_min_l=ReadLine (NET_RECEIVE_STREAM)
OPTION_planet_max_r=ReadLine (NET_RECEIVE_STREAM)
OPTION_planet_max_l=ReadLine (NET_RECEIVE_STREAM)
OPTION_planet_anzahl=ReadLine (NET_RECEIVE_STREAM)
DebugLog OPTION_planet_anzahl
NEXT_MENUE=1
SCH_CREATE(\"Zurrück\",\"Zurrück\",100,SYS_GFX_Y/6*4,\"GFX\Menü\Mainmenu\options1.png\",\"GFX\Menü\Mainmenu\options2.png\",\"\",\"\",1,1)

Case 4
;Spielstart
NEXT_MENUE=1

Case 5;DEBUGMESSAGE
DebugLog ReadLine(NET_RECEIVE_STREAM)

Case 6;Neuen Spieler registrieren/ Spieler löschen
Select ReadByte (NET_RECEIVE_STREAM)
Case 1;Neuen eintragen
player.player=New player
player\name=ReadLine(NET_RECEIVE_STREAM)
player\farbe=ReadLine(NET_RECEIVE_STREAM)
player\IP=ReadInt(NET_RECEIVE_STREAM)
player\PORT=ReadInt(NET_RECEIVE_STREAM)
Case 2;Spieler löschen
zs_name$=ReadLine(NET_RECEIVE_STREAM)
For player.player=Each player
If player\name=zs_name Delete player
Next
End Select

Case 7;Planeten erstellen

planet.planet=New planet
planet\name$=ReadLine(NET_RECEIVE_STREAM)
planet\Typ=ReadInt(NET_RECEIVE_STREAM);Planetentyp
planet\ID=ReadInt(NET_RECEIVE_STREAM)
planet\PlayerID=ReadInt(NET_RECEIVE_STREAM);Besitzer des Planeten
planet\big_R=ReadInt(NET_RECEIVE_STREAM);Anzahl der Tile-Felder in R Richtung
planet\big_L=ReadInt(NET_RECEIVE_STREAM);Anzahl der Tile-Felder in L Richtung
planet\bigness#=ReadFloat(NET_RECEIVE_STREAM);big_R*big_L/Maximal möglich
planet\xpos#=ReadFloat(NET_RECEIVE_STREAM)
planet\ypos#=ReadFloat(NET_RECEIVE_STREAM)
planet\drehgeschwindigkeitx#=ReadFloat(NET_RECEIVE_STREAM);Mit der sich der Planet dreht
planet\drehgeschwindigkeity#=ReadFloat(NET_RECEIVE_STREAM)
planet\temperatur=ReadInt(NET_RECEIVE_STREAM);Schnickschnak
planet\mesh1=CreateSphere(OPTION_PLANETENDETAIL);Masse
zs_tex=LoadTexture(\"GFX\Planeten\\"+planet\Typ+\".jpg\",8)
EntityTexture planet\mesh1,zs_tex
EntityFX planet\mesh1,1
planet\mesh2=CreateSphere(OPTION_PLANETENDETAIL,planet\mesh1);Atmosphäre
;Anpassen an den Planeten
ScaleEntity planet\mesh1,planet\bigness,planet\bigness,planet\bigness
ScaleEntity planet\mesh2,1.1,1.1,1.1,0
EntityAlpha planet\mesh2,0.2
PositionEntity planet\mesh1,planet\xpos,planet\ypos,0
planet\kohlesekunde#=0;Wieviel pro Sekunde dazukommt
planet\kohlemod#=0;Modifikator auf Kohle (durch Gebäude)
planet\KnowHowsekunde#=0;Wieviel pro Sekunde dazukommt
planet\knowhowmod#=0;Modifikator auf Know-How (durch Gebäude)
planet\Energiesekunde#=0;Wieviel pro Sekunde dazukommt
planet\energiemod#=0;Modifikator auf Energie (durch Gebäude)

tmp_stream=WriteFile(\"Data\TMP\\"+planet\ID+\".planet\")
For r=1 To planet\big_R
For l=1 To planet\big_L
WriteByte tmp_stream,ReadByte(NET_RECEIVE_STREAM)
WriteByte tmp_stream,0
Next
Next
CloseFile tmp_stream
DebugLog \"Planeteninfo bekommen:\"+planet\ID
WriteByte NET_SEND_STREAM,1
SendUDPMsg NET_SEND_STREAM,NET_SERVER_IP,NET_SERVER_PORT


Default
WriteLine NET_SEND_STREAM,\"ERROR: Commandbyte not used\"
SendUDPMsg NET_SEND_STREAM,IP,sc_port-1
End Select
EndIf



Until sc_IP=0
;Ende
End Function
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Mathias-Kwiatkowski

BeitragSo, Aug 28, 2005 2:05
Antworten mit Zitat
Benutzer-Profile anzeigen
naja gut ok du arbeitest mit udp... damit kenn ich mich nicht wirklich aus, tcp währe einfacher!!! (für mich) aber leider nicht fürs game da udp schneller ist, aller dings kann es bei udp ja auch sein das etwas nicht ankommt...

naja strucktur, dein code is doch eigentlich übersichtlich...

du kannst ja auch mehere proceduren machen oder mit dem befehl include machen, so bleibt das hauptproggi übersichtlicher!!

falls ich in einer weise daneben lieg sorry!

aber ich würde es z.b. etwa so machen

---->
hauptproggi
include "playerdaten.bb"
include "welt.bb"

player(x,y) ;also z.b. wo sich der player befindet
welt(grösse, ("alles was du noch brauchst für deine welt"))


nebenproggi playerdaten
function player(x,y) ;also z.b. wo sich der player befindet


nebenproggi welt.bb
function weltwelt(grösse, ("alles was du noch brauchst für deine welt"))
<-----

so in etwa würde ich es machen!!

dann hast du eigentlich eine übersicht!! auf alle quelltexte, und du verlierst dich darin nicht! und muss nicht lange suchen!

wenns geholfen hat sag bescheid, danke

Firstdeathmaker

BeitragSo, Aug 28, 2005 11:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Hat mir jetzt nicht so wirklich geholfen, da ich den oben eingefügten Code eh schon in einer Include hatte. Und ne Funktion "Player" halte ich für sehr überflüssig, oder hab den Sinn und Zweck noch nicht so ganz kapiert. Ich mach normalerweise eine Gamehauptschleife in der alle Objekte upgedatet werden, das ist soweit schon recht Übersichtlich, hab also keine probleme mit dem Strukturieren allgemein, sondern mit den speziellen Strukturen die für einen Multiplayershooter notwendig sind.


Was vielmehr mein Problem ist: Wie bekomme ich es genau hin, die Spiele zu synchronisieren ohne zu viel Bandbreite zu verballern? Reicht es wirklich aus, immer nur die Änderung der Geschwindigkeit und Richtung zu senden? Wird das nicht auf die Dauer etwas ungenau? Was ist mit der Ping-Time, die sorgt doch dafür dass die Daten erst etwas verzögert ankommen, müsste man dann nicht eine globale (Computerübergreifende) Zeiut einführen und dann bei Sendungen diese mitschicken, sodass der andere Computer auch sieht, wann die Veränderung statt gefunden hat, und dann dementsprechend zurück rechnet? Oder ist das zuviel Aufwand, und bringt eigentlich nicht so viel?

Meine eigentliche Frage war eigentlich: Macht man es generell so, dass man eine Funktion (wie z.B. meine oben genannte) schreibt, in der alle Netzwerkdaten angenommen und verarbeitet werden, oder gibt es da noch andere Möglichkeiten?
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image
 

BIG BUG

BeitragSo, Aug 28, 2005 18:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich arbeite auch gerade an einem kleinen 2D-NetzwerkSpaceShooter(extra um mal ein bisschen Praxis in diesem Netzwerkkram zu bekommen). Bei mir gibt es aber nur 4 Bewegungsrichtungen, was die Sache etwas vereinfacht.

Ich habe es so gemacht, dass wenn der Spieler die Bewegungsrichtung ändert oder schießt einfach die Position sowie die neue Richtung an alle Mitspieler versendet wird(also P2P). Schüsse werden so ebenfalls nur erstellt und dann von jedem Client selbst berechnet.
Trifft ein Schuss, so wird dieser bei jedem Spieler erst nur deaktiviert, der "Einschlag" muss dann vom Erzeuger mit exakter Position bestätigt werden.
Also immer wenn was passiert, schicke ich auch die genaue Postitionsangabe mit und jeder Spieler verwaltet sich selbst und seine erzeugten Schüsse.

Damit keine Startplätze doppelt belegt werden, wird vom Server zufällig eine Basisnummer erzeugt und eine eindeutige Spielernummer vergeben. Basisnummber+Spielernummer ergibt dann die Nummer des Startplatzes.

Einen Latency(Verzögerung)-Ausgleich oder Paketkontrolle(wegen UDP) habe ich noch nicht eingebaut, eine kleine Netzwerkschlacht mit 8 Spielern hatte aber trotzdem schon gut funktioniert.

Damit das Ganze dann auch im Internet gut läuft werde ich beides aber wohl noch einbauen.

Ansonsten werden alle Messages vor meiner Updatefunktion gesammelt und in einen Type gestellt(die Daten die bei jeder Message gleich sind, wie Messageart/sendender Spieler/IP/Port/Paketnummer etc.)
In einer zusätzlichen Bank werden dann die messageabhängigen Daten wie Postitionsangaben abgespeichert.
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)

Firstdeathmaker

BeitragSo, Aug 28, 2005 19:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Den letzten Teil hab ich noch nicht so wirklich verstanden:

Zitat:
Ansonsten werden alle Messages vor meiner Updatefunktion gesammelt und in einen Type gestellt(die Daten die bei jeder Message gleich sind, wie Messageart/sendender Spieler/IP/Port/Paketnummer etc.)
In einer zusätzlichen Bank werden dann die messageabhängigen Daten wie Postitionsangaben abgespeichert.


Was hat das für einen Sinn und Zweck wenn du die Messages abspeicherst?
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image
 

BIG BUG

BeitragSo, Aug 28, 2005 21:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Ob das so sinnvoll ist weiß ich selbst auch noch nicht Smile . Ist ja auch noch in der Entwicklung.

Erstmal war mir wichtig eine eigene Schnittstelle zu den Netzwerkbefehlen zu schaffen, um später testweise dann auch einfach auf TCP wechseln zu können und an jedes Paket unnütze Last dranhängen zu können(für Lasttests).
Egal ob Lobby oder Spiel, die Netzwerkroutinen bleiben die gleichen.
Dann wäre dann noch das zusammenfassen von Paketen(z.B. bei mehreren lokalen Spielern) und Paketsicherung...
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group