NetzwerkSpiel - Ich schaffs nicht :/

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Düsi

Betreff: NetzwerkSpiel - Ich schaffs nicht :/

BeitragFr, Jun 27, 2008 14:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich versuche mich gerade an einem kleinem kleinem NetzwerkSpiel.

Ich bekomm es aber einfach nicht hin, damit die Mitspieler bei allen Clients richtig Angezeigt werden. :/

Wenn ich einen Client starte, sendet er die X/Y Position und den NickName an den "Server", das habe ich hinbekommen. (Und erstellt einen neuen Eintrag in dem Type "player"&"client", dadurch bekommt der Client dann seine ID)

Dann sende ich in jeder Runde (der Hauptschleife) die aktuelle Position der Spielefigur. - Das klappt auch noch.

Jetzt möchte ich aber in jeder Runde der Hauptschleife vom Server alle Clients durchgehen, die gesendete Position wieder in den Type player&client speichern <-- das geht ja noch und dann wieder an alle verbundenen Clients zurücksenden (dazu 2 Types, ich habs anders nicht geschafft >.<).
Das will aber einfach nicht funktionieren. / Beim ersten Client wo ich starte wird die Figur vom zweiten Client wo ich starte nicht angezeigt, beim zweiten Client wird die vom ersten Client angezeigt, bewegt sich aber nicht. - Beim Server werden jedoch die Position noch verändert.


Code: [AUSKLAPPEN]
Server:

;Alle Types durchgehen
For player = Each player
   ;Types abgleichen
   For client = Each client
      If client\id = player\id Then
         client\x = player\x
         client\y = player\y
      EndIf
   Next
      
   ;### SENDEN ###; <-- klappt nicht...   
   ;Position der Anderen Spielern an den Client senden
   For client = Each client
      WriteString player\stream, "UpdatePlayerID."+client\id
      WriteString player\stream, client\name
      WriteString player\stream, client\x
      WriteString player\stream, client\y
   Next    
Next     


Client:
;Informationen jedes Spielers vom Server abfragen
ReadServerTmp = ReadString(Server)

If ReadServerTmp <> "" And ReadServerTmp <> 0 Then
   
   intype = 0 ;Zum prüfen, ob der Spieler bereits auf dem Client existiert
      
   ;Prüfen, ob UpdatePlayerID dabei seht
   p1 = Instr(ReadServerTmp, "UpdatePlayerID.")
   If p1 <> 0 Then
      ;Wenn ja, ID speichern
      playerID = Right(ReadServerTmp, Len(ReadServerTmp)-p1-14)
         
      ;Alle Spieler durchgehen
      For player = Each player
         ;Und prüfen, ob es der richtige Spieler ist
         If playerID = player\id Then
            
            ;Wenn ja, Type erneuern
            player\name = ReadString(Server)
            player\x = ReadString(Server)
            player\y = ReadString(Server)
                              
            intype = 1
         EndIf
      Next
         
      If update = 0 And playerID <> ID Then
         ;Wenn nichts gefunden wurde, neuen Spieler erstellen
         player = New player
         player\id = playerID
         player\name = ReadString(Server)
         player\x = ReadString(Server)
         player\y = ReadString(Server)
      EndIf
   EndIf
EndIf



Könnte das ganze so überhaupt klappen oder ist schon mein Ansatz falsch?

Ich bedanke mich schonmal für eure (hoffentliche) hilfe.

MfG

ToeB

BeitragFr, Jun 27, 2008 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich versteh den code zwar nicht, aber du kannst es anders machen :

Code: [AUSKLAPPEN]
Graphics 800,600,16,2
SetBuffer BackBuffer()

Global p_anz = 1
Global Server = 0
Global send_ms = MilliSecs() ;Variable fürs Senden, damit nicht jeen schleifen durchgang gesendet werden muss
Global Send_in = 25 ;Intervallen, in denen gesenden wird (in ms)
Global SEND_STREAM
Global RECV_STREAM
Global SEND_PORT
Global RECV_PORT
Global GET_MSG

Const MSG = 1
Const QUEST = 2
Const NO_P = 3
Const GET_HOST = 4

Dim Cl$(39)

Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz)  ;Die Wichtigsten Functionen

Dim chat$(p_anz),SetChat(P_anz) ;Positionen im Spiel (Hier ein Chat)

Dim GETHOST_IP(64)
Dim GETHOST_N$(64)

;HOST / JOIN Abfrage :
Print "HOST(1)  /  JOIN(2)"
Server = Input(">>")
If Server < 1 Then Server = 1 ;HOST
If Server > 2 Then Server = 2 ;JOIN

;Weitere Abfragen :
Select Server
Case 1
   SEND_PORT = 8000
   RECV_PORT = 8001
   ;Namen :
   Print "Name : "
   Name_$ = Input(">>")
   ;Spieleranzahl :
   Print "Spieler anzahl : "
   Print "1 : 4"
   Print "2 : 8"
   Print "3 : 16"
   Print "4 : 24"
   Print "5 : 32"
   Print "6 : 64"
   p_anz = Input(">>")
   If p_anz < 1 Then p_anz = 1
   If p_anz > 6 Then p_anz = 6
   Select p_anz
   Case 1
      p_anz = 4
   Case 2
      p_anz = 8
   Case 3
      p_anz = 16
   Case 4
      p_anz = 24
   Case 5
      p_anz = 32
   Case 6
      p_anz = 64
   End Select
   DimNew(p_anz)
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   acc(1) = 1
   Name(1) = Name_
   ID = 1
Case 2
   SEND_PORT = 8001
   RECV_PORT = 8000
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   ;Namen :
   Print "Name : "
   Name_$ = Input(">>")
   Print "Was willst du tun ?"
   Print "1 : IP eingeben"
   Print "2 : IP aus Liste auswählen"
   wahl = Input(">>")
   If wahl < 1 Then wahl = 1
   If wahl > 2 Then wahl = 2
   Select wahl
   Case 1
      Print "Server IP : "
      IP(1) = INT_IP(Input(">>"))
   Case 2
      IP(1) = INT_IP(BroadcastIP())
      WriteByte(SEND_STREAM,GET_HOST)
      SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
      wahl = 0
      Cls
      Locate 0,0
      Print "Drücke enter um einen auszuwählen"
      Delay 100
      FlushKeys()
      Repeat
         If RecvUDPMsg(RECV_STREAM)
            If ReadByte(RECV_STREAM) = GET_HOST Then
               If wahl < 64 Then
                  namen$ = ReadString(RECV_STREAM)
                  wahl = wahl + 1
                  GETHOST_IP(wahl) = UDPMsgIP(RECV_STREAM)
                  GETHOST_N$(wahl) = namen
                  Print wahl + " : "+GETHOST_N$(wahl)+" ("+DottedIP(GETHOST_IP(wahl))+")"
               EndIf
            EndIf
         EndIf
         If KeyHit(1) Then End
      Until KeyHit(28)
      max_wa = wahl
      Delay 100
      FlushKeys()
      Print "Deine Wahl : "
      wahl = Input(">>")
      If wahl < 1 Then wahl = 1
      If wahl > max_wa Then wahl = max_wa
      IP(1) = GETHOST_IP(wahl)
   End Select
   WriteByte(SEND_STREAM,QUEST)
   WriteString(SEND_STREAM,Name_$)
   SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
   Print "Bitte Warten..."
   wait_ms = MilliSecs() + 1000
   Repeat
      If RecvUDPMsg(RECV_STREAM)
         If ReadByte(RECV_STREAM) = QUEST
            ID = ReadByte(RECV_STREAM)
            p_anz = ReadByte(RECV_STREAM)
            IPIP = IP(1)
            DimNew(p_anz)
            IP(1) = IPIP
            acc(ID) = 1
            Name(ID) = Name_
            For i = 1 To p_anz
               IDID = ReadByte(RECV_STREAM)
               name(IDID) = ReadString(RECV_STREAM)
               acc(IDID) = 1
               TimeOut(IDID) = MilliSecs() + 1000
            Next
            Exit
         Else
            Print "Serverliste voll !"
            Delay 2500
            End
         EndIf
      EndIf
      If wait_ms <= MilliSecs()
         Print "Server hat nicht geantwortet !"
         Delay 2500
         End
      EndIf
      If KeyHit(1) Then End
   Forever    
   GET_MSG = 1
End Select
;zz = acc(1)
;Schleife
Repeat
   ;Hier die ganzen Steuerungs-abfragen, etc...
   zeile = 0
   For i = 1 To p_anz
      If acc(i) Then
         Text 0,zeile*15,i+".: "+Name(i)
         zeile = zeile + 1
      EndIf
   Next
   g = GetKey()
   If g > 0 And g <> 8 And g <> 13 Then Ch$ = Ch$ + Chr(g)
   If g = 8 Then Ch$ = Left(Ch$,Len(Ch$)-1)
   If g = 13 And ch <> "" Then
      Chat(ID) = ch
      ch = ""
      NewChatLine(Name(ID)+":"+Chat(ID))
   EndIf
   For i =1 To p_anz
      If i <> ID And Chat(i) <> "" And SetChat(i) = 0
         NewChatLine(Name(i)+":"+Chat(i))
         If Server = 1
            SetChat(i) = 1
         Else
            Chat(i) = ""
         EndIf
      EndIf
   Next
   Text 150,0,"Chat:"+ch
   Rect 150,15,650,1
   For i = 1 To 39
      Text 150,0+i*15,cl(i)
   Next
   ;Hier das ganze senden von Dateien
   Select Server
   Case 1
      If send_ms <= MilliSecs() Then
         For SEND_PLAYER = 2 To p_anz ;An die Spieler senden
            If acc(SEND_PLAYER) = 1 Then ;Wenn Player online ist
               WriteByte(SEND_STREAM,MSG) ;BYte für normal Nachricht (Positionen etc...)
               For POS_PLAYER = 1 To p_anz ;Positionen von Spielern
                  If POS_PLAYER <> SEND_PLAYER ;Damit keiner seine eigenen Daten bekommt und sich daher nicht bewegen (o.ä.) kann ^^
                     If acc(POS_PLAYER) = 1 Then
                        WriteByte(SEND_STREAM,POS_PLAYER) ;ID vom aktuellen Player als erstes schiken
                        ;Hier weitere Sachen schiken
                        WriteString(SEND_STREAM,Chat(POS_PLAYER))
                        If New_p(POS_PLAYER) = 1 Then WriteString(SEND_STREAM,name(POS_PLAYER))
                        ;/\__--Ist wenn ein neuer Spieler
                        ;dazugekommen ist, damit die anderen wissen, wie er heißt (man kann zusätzlich auch noch andere Standart-
                        ;informationen senden, die nicht die ganze Zeit mitgesendet werden müssen, weil sie immer gleich bleiebn,
                        ;z.b. Farbe oder Team...
                     EndIf
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(SEND_PLAYER),SEND_PORT) ;Alles senden
            EndIf
         Next
         For i = 1 To p_anz
            New_p(i) = 0
            Chat(i) = ""
            SetChat(i) = 0
         Next
         send_ms = MilliSecs() + send_in ;Wieder zurücksetzten, damit der Intervall auch bleibt
      EndIf
   Case 2
      If GET_MSG = 1 Then ;Wenn der CLIENT eine Nachricht vom Host erhalten hat...
         WriteByte(SEND_STREAM,MSG) ;Normale Nachricht
         WriteByte(SEND_STREAM,ID);Eigene ID
         ;Andere Daten...
         WriteString(SEND_STREAM,Chat(ID))
         SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
         CHAT(ID) = ""
         GET_MSG = 0
      EndIf
   End Select
   ;Hier die ganzen Daten empfangen / verarbeiten
   While RecvUDPMsg(RECV_STREAM) ;Während empfamngen wird, schleife nicht beenden...
      byte = ReadByte(RECV_STREAM) ;Byte für orientierung
      Select Server
      Case 1
         Select byte
         Case MSG ;Normale Nachricht
            IDID = ReadByte(RECV_STREAM) ;ID des Clienten auslesen
            ;Andere sachen für ID : IDID auslesen
            Chat(IDID) = ReadString(RECV_STREAM)
            TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut wieder auf 1 Sekunde setzten
         Case QUEST
            ;Gucken, ob noch ein platz frei ist, und dann welcher
            IDID = 0
            For i = 2 To p_anz
               If acc(i) = 0 Then IDID = i:Exit
            Next
            If IDID Then ;Wenn platzt frei
               Name(IDID) = ReadString(RECV_STREAM) ;NAmen auslesen
               New_p(IDID) = 1
               acc(IDID) = 1
               IP(IDID) = UDPMsgIP(RECV_STREAM) ;IP herausfinden
               WriteByte(SEND_STREAM,QUEST)
               WriteByte(SEND_STREAM,IDID)
               WriteByte(SEND_STREAM,p_anz)
               For i = 1 To p_anz
                  If i <> IDID And acc(i)
                     WriteByte(SEND_STREAM,i)
                     WriteString(SEND_STREAM,name(i))
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(IDID),SEND_PORT)
               TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut auf 1 Sekunde setzten
            Else ;Wenn kein Platzt frei
               WriteByte(SEND_STREAM,NO_P) ;Sende "Kein Platzt"
               SendUDPMsg(SEND_STREAM,UDPMsgIP(RECV_STREAM),SEND_PORT)
            EndIf
         Case GET_HOST
            max_p = 0
            For i = 1 To p_anz
               If acc(i) Then max_p = max_p + 1
            Next
            namen$ = name(1)+"  "+max_p+"/"+p_anz
            WriteByte(SEND_STREAM,GET_HOST)
            WriteString(SEND_STREAM,namen$)
            SendUDPMsg(SEND_STREAM,UDPMsgIP(Recv_STREAM),SEND_PORT)
         End Select          
      Case 2
         Select byte
         Case MSG
            While Not Eof(RECV_STREAM)
               IDID = ReadByte(RECV_STREAM) ;ID auslesen
               If IDID > 0
                  chat(IDID) = ReadString(RECV_STREAM)
                  If acc(IDID) = 0 Then ;Wenn die ID vorher nicht online war ...
                     acc(IDID) = 1 ;Online machen xD
                     name(IDID) = ReadString(RECV_STREAM)
                     ;Oder halt noch die Standartinformationen (siehe oben bei Senden...)
                  EndIf
                  TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut wieder auf 1 Sekunde setzten
               EndIf
            Wend
            GET_MSG = 1 ;Nachricht bekommen
         End Select             
      End Select
      If KeyHit(1) Then End
   Wend
      
   ;TimeOut :
   For i = 1 To p_anz
      If acc(i) And i <> ID ;Wenn online aber nicht die eigene IP
         If TimeOut(i) <= MilliSecs() Then acc(i) = 0 ;Wenn TimeOut (1s) abgelaufen, rausschmiss
      EndIf
   Next
   ;Timeout heiß so viel wie dass man 1s lang keine nachricht mehr von dem jenigen bekommen hat, heit er hat ca 40 nachrichten
   ;nicht bekommen von ihm...
   If acc(1) = 0 ; Wenn Server nicht mehr da ...
      Cls
      Flip
      Text 400,100,"Server hat das Spiel verlassen...",1
      Text 400,400,"-Taste zum Beenden drücken-",1
      Delay 100
      WaitKey()
      End ; ...Beenden ^^
   EndIf    
   Flip
   Cls
Until KeyHit(1)
End


Function INT_IP(IP$)
   If Instr(IP$,".") <> 0 a1=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a2=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a3=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   a4=Int(IP$)
   Return (a1 Shl 24) + (a2 Shl 16) + (a3 Shl 8 ) +a4
End Function
         
                  

Function DimNew(NewAnz)
   
   p_anz = NewAnz
   Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz)  ;Die Wichtigsten Functionen
   
   Dim Chat(p_anz),SetChat(p_anz)  ;Positionen im Spiel (Hier Chat)
   
End Function

Function BroadcastIP$()
 
   CountHostIPs("")
   Local IP$ = DottedIP(HostIP(1))
   
   Local Subnetmask$ = "255.255.255.0"
   
   Local IPDigits[3], SubnetDigits[3]
   Local pos, i
   
   ; IP aufteilen
   For i = 0 To 3
      pos = Instr( IP$, "." )
      If pos > 0
         IPDigits[i] = Left( IP$, pos -1 )
         IP$ = Mid( IP$, pos +1 )
      Else
         IPDigits[i] = IP$
      EndIf
   Next
   
   ; Subnetmask aufteilen &invertieren
   For i = 0 To 3
      pos = Instr( Subnetmask$, "." )
      If pos > 0
         SubnetDigits[i] = Left( Subnetmask$, pos -1 ) Xor $FF
         Subnetmask$ = Mid( Subnetmask$, pos +1 )
      Else
         SubnetDigits[i] = Subnetmask$ Xor $FF
      EndIf
   Next
   
   ; IP maskieren
   For i = 0 To 3
      IPDigits[i] = IPDigits[i] Or SubnetDigits[i]
   Next
   
   Return IPDigits[0] +"." +IPDigits[1] +"." +IPDigits[2] +"." +IPDigits[3]
   
End Function

Function NewChatLine(txt$)
   
   If txt$ <> ""
      For i = 39 To 1 Step -1
         cl(i) = cl(i-1)
      Next
      cl(1) = txt$
   EndIf
   
End Function


Das ist ein kleines Ausführliches programm von mir (kleiner Chat), mit vielen Kommentaren und gut erklärt. Ich hab es so geschrieben, dass man ohne Probleme jedes LAN Spiel daraus machen kann...

Probier es einfach mal aus und baue sachen ein...

Version ohne Kommentra (zum ausbauen ) :
Code: [AUSKLAPPEN]
Graphics 800,600,16,2
SetBuffer BackBuffer()

Global p_anz = 1
Global Server = 0
Global send_ms = MilliSecs()
Global Send_in = 25
Global SEND_STREAM
Global RECV_STREAM
Global SEND_PORT
Global RECV_PORT
Global GET_MSG

Const MSG = 1
Const QUEST = 2
Const NO_P = 3
Const GET_HOST = 4

Dim Cl$(39)

Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz) 

Dim chat$(p_anz),SetChat(P_anz)

Dim GETHOST_IP(64)
Dim GETHOST_N$(64)


Print "HOST(1)  /  JOIN(2)"
Server = Input(">>")
If Server < 1 Then Server = 1
If Server > 2 Then Server = 2

Select Server
Case 1
   SEND_PORT = 8000
   RECV_PORT = 8001
   Print "Name : "
   Name_$ = Input(">>")
   
   Print "Spieler anzahl : "
   Print "1 : 4"
   Print "2 : 8"
   Print "3 : 16"
   Print "4 : 24"
   Print "5 : 32"
   Print "6 : 64"
   p_anz = Input(">>")
   If p_anz < 1 Then p_anz = 1
   If p_anz > 6 Then p_anz = 6
   Select p_anz
   Case 1
      p_anz = 4
   Case 2
      p_anz = 8
   Case 3
      p_anz = 16
   Case 4
      p_anz = 24
   Case 5
      p_anz = 32
   Case 6
      p_anz = 64
   End Select
   DimNew(p_anz)
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   acc(1) = 1
   Name(1) = Name_
   ID = 1
Case 2
   SEND_PORT = 8001
   RECV_PORT = 8000
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   Print "Name : "
   Name_$ = Input(">>")
   Print "Was willst du tun ?"
   Print "1 : IP eingeben"
   Print "2 : IP aus Liste auswählen"
   wahl = Input(">>")
   If wahl < 1 Then wahl = 1
   If wahl > 2 Then wahl = 2
   Select wahl
   Case 1
      Print "Server IP : "
      IP(1) = INT_IP(Input(">>"))
   Case 2
      IP(1) = INT_IP(BroadcastIP())
      WriteByte(SEND_STREAM,GET_HOST)
      SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
      wahl = 0
      Cls
      Locate 0,0
      Print "Drücke enter um einen auszuwählen"
      Delay 100
      FlushKeys()
      Repeat
         If RecvUDPMsg(RECV_STREAM)
            If ReadByte(RECV_STREAM) = GET_HOST Then
               If wahl < 64 Then
                  namen$ = ReadString(RECV_STREAM)
                  wahl = wahl + 1
                  GETHOST_IP(wahl) = UDPMsgIP(RECV_STREAM)
                  GETHOST_N$(wahl) = namen
                  Print wahl + " : "+GETHOST_N$(wahl)+" ("+DottedIP(GETHOST_IP(wahl))+")"
               EndIf
            EndIf
         EndIf
         If KeyHit(1) Then End
      Until KeyHit(28)
      max_wa = wahl
      Delay 100
      FlushKeys()
      Print "Deine Wahl : "
      wahl = Input(">>")
      If wahl < 1 Then wahl = 1
      If wahl > max_wa Then wahl = max_wa
      IP(1) = GETHOST_IP(wahl)
   End Select
   WriteByte(SEND_STREAM,QUEST)
   WriteString(SEND_STREAM,Name_$)
   SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
   Print "Bitte Warten..."
   wait_ms = MilliSecs() + 1000
   Repeat
      If RecvUDPMsg(RECV_STREAM)
         If ReadByte(RECV_STREAM) = QUEST
            ID = ReadByte(RECV_STREAM)
            p_anz = ReadByte(RECV_STREAM)
            IPIP = IP(1)
            DimNew(p_anz)
            IP(1) = IPIP
            acc(ID) = 1
            Name(ID) = Name_
            For i = 1 To p_anz
               IDID = ReadByte(RECV_STREAM)
               name(IDID) = ReadString(RECV_STREAM)
               acc(IDID) = 1
               TimeOut(IDID) = MilliSecs() + 1000
            Next
            Exit
         Else
            Print "Serverliste voll !"
            Delay 2500
            End
         EndIf
      EndIf
      If wait_ms <= MilliSecs()
         Print "Server hat nicht geantwortet !"
         Delay 2500
         End
      EndIf
      If KeyHit(1) Then End
   Forever    
   GET_MSG = 1
End Select

Repeat
   
   zeile = 0
   For i = 1 To p_anz
      If acc(i) Then
         Text 0,zeile*15,i+".: "+Name(i)
         zeile = zeile + 1
      EndIf
   Next
   g = GetKey()
   If g > 0 And g <> 8 And g <> 13 Then Ch$ = Ch$ + Chr(g)
   If g = 8 Then Ch$ = Left(Ch$,Len(Ch$)-1)
   If g = 13 And ch <> "" Then
      Chat(ID) = ch
      ch = ""
      NewChatLine(Name(ID)+":"+Chat(ID))
   EndIf
   For i =1 To p_anz
      If i <> ID And Chat(i) <> "" And SetChat(i) = 0
         NewChatLine(Name(i)+":"+Chat(i))
         If Server = 1
            SetChat(i) = 1
         Else
            Chat(i) = ""
         EndIf
      EndIf
   Next
   Text 150,0,"Chat:"+ch
   Rect 150,15,650,1
   For i = 1 To 39
      Text 150,0+i*15,cl(i)
   Next
   
   Select Server
   Case 1
      If send_ms <= MilliSecs() Then
         For SEND_PLAYER = 2 To p_anz
            If acc(SEND_PLAYER) = 1 Then
               WriteByte(SEND_STREAM,MSG)
               For POS_PLAYER = 1 To p_anz
                  If POS_PLAYER <> SEND_PLAYER
                     If acc(POS_PLAYER) = 1 Then
                        WriteByte(SEND_STREAM,POS_PLAYER)
                        WriteString(SEND_STREAM,Chat(POS_PLAYER))
                     EndIf
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(SEND_PLAYER),SEND_PORT)
            EndIf
         Next
         For i = 1 To p_anz
            New_p(i) = 0
            Chat(i) = ""
            SetChat(i) = 0
         Next
         send_ms = MilliSecs() + send_in
      EndIf
   Case 2
      If GET_MSG = 1 Then
         WriteByte(SEND_STREAM,MSG)
         WriteByte(SEND_STREAM,ID)
         
         WriteString(SEND_STREAM,Chat(ID))
         SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
         CHAT(ID) = ""
         GET_MSG = 0
      EndIf
   End Select
   
   While RecvUDPMsg(RECV_STREAM)
      byte = ReadByte(RECV_STREAM)
      Select Server
      Case 1
         Select byte
         Case MSG
            IDID = ReadByte(RECV_STREAM)
            Chat(IDID) = ReadString(RECV_STREAM)
            TimeOut(IDID) = MilliSecs() + 1000
         Case QUEST
            
            IDID = 0
            For i = 2 To p_anz
               If acc(i) = 0 Then IDID = i:Exit
            Next
            If IDID Then
               Name(IDID) = ReadString(RECV_STREAM)
               New_p(IDID) = 1
               acc(IDID) = 1
               IP(IDID) = UDPMsgIP(RECV_STREAM)
               WriteByte(SEND_STREAM,QUEST)
               WriteByte(SEND_STREAM,IDID)
               WriteByte(SEND_STREAM,p_anz)
               For i = 1 To p_anz
                  If i <> IDID And acc(i)
                     WriteByte(SEND_STREAM,i)
                     WriteString(SEND_STREAM,name(i))
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(IDID),SEND_PORT)
               TimeOut(IDID) = MilliSecs() + 1000
            Else
               WriteByte(SEND_STREAM,NO_P)
               SendUDPMsg(SEND_STREAM,UDPMsgIP(RECV_STREAM),SEND_PORT)
            EndIf
         Case GET_HOST
            max_p = 0
            For i = 1 To p_anz
               If acc(i) Then max_p = max_p + 1
            Next
            namen$ = name(1)+"  "+max_p+"/"+p_anz
            WriteByte(SEND_STREAM,GET_HOST)
            WriteString(SEND_STREAM,namen$)
            SendUDPMsg(SEND_STREAM,UDPMsgIP(Recv_STREAM),SEND_PORT)
         End Select          
      Case 2
         Select byte
         Case MSG
            While Not Eof(RECV_STREAM)
               IDID = ReadByte(RECV_STREAM)
               If IDID > 0
                  chat(IDID) = ReadString(RECV_STREAM)
                  If acc(IDID) = 0 Then
                     acc(IDID) = 1
                     name(IDID) = ReadString(RECV_STREAM)
                     
                  EndIf
                  TimeOut(IDID) = MilliSecs() + 1000
               EndIf
            Wend
            GET_MSG = 1
         End Select             
      End Select
      If KeyHit(1) Then End
   Wend
      
   
   For i = 1 To p_anz
      If acc(i) And i <> ID
         If TimeOut(i) <= MilliSecs() Then acc(i) = 0
      EndIf
   Next
   
   If acc(1) = 0
      Cls
      Flip
      Text 400,100,"Server hat das Spiel verlassen...",1
      Text 400,400,"-Taste zum Beenden drücken-",1
      Delay 100
      WaitKey()
      End
   EndIf    
   Flip
   Cls
Until KeyHit(1)
End


Function INT_IP(IP$)
   If Instr(IP$,".") <> 0 a1=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a2=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a3=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   a4=Int(IP$)
   Return (a1 Shl 24) + (a2 Shl 16) + (a3 Shl 8 ) +a4
End Function
         
                  

Function DimNew(NewAnz)
   
   p_anz = NewAnz
   Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz) 
   
   Dim Chat(p_anz),SetChat(p_anz) 
   
End Function

Function BroadcastIP$()
 
   CountHostIPs("")
   Local IP$ = DottedIP(HostIP(1))
   
   Local Subnetmask$ = "255.255.255.0"
   
   Local IPDigits[3], SubnetDigits[3]
   Local pos, i
   
   
   For i = 0 To 3
      pos = Instr( IP$, "." )
      If pos > 0
         IPDigits[i] = Left( IP$, pos -1 )
         IP$ = Mid( IP$, pos +1 )
      Else
         IPDigits[i] = IP$
      EndIf
   Next
   
   
   For i = 0 To 3
      pos = Instr( Subnetmask$, "." )
      If pos > 0
         SubnetDigits[i] = Left( Subnetmask$, pos -1 ) Xor $FF
         Subnetmask$ = Mid( Subnetmask$, pos +1 )
      Else
         SubnetDigits[i] = Subnetmask$ Xor $FF
      EndIf
   Next
   

   For i = 0 To 3
      IPDigits[i] = IPDigits[i] Or SubnetDigits[i]
   Next
   
   Return IPDigits[0] +"." +IPDigits[1] +"." +IPDigits[2] +"." +IPDigits[3]
   
End Function

Function NewChatLine(txt$)
   
   If txt$ <> ""
      For i = 39 To 1 Step -1
         cl(i) = cl(i-1)
      Next
      cl(1) = txt$
   EndIf
   
End Function


Bei Fragen bitte melden..

Ich hoffe du kannst was damit anfangen..

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

Düsi

BeitragFr, Jun 27, 2008 22:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke erstmal. Smile

Dein Code ist jetzt aber nicht ganz so, wie ich es eigtl. machen wollte. Ich wollte 2 Dateien haben, einmal das Spiel, mit diesem man sich dann über Hamachi zu dem PC verbindet, wo die ServerDatei gestartet ist, also damit nur derjenige wo auch die Server Datei hat, einen Server eröffnen kann.

Da meine Beschreibung oben wohl etwas zu ungenau war:
Mein Ansatz ging so: Wenn man den Client startet, sendet er an den Server, damit es einen neuen Client gibt, der Server weißt diesem dann eine ID zu und sendet es dem Client dann. In jeder Runde dere Hauptschleife der Clients wird dann die Aktuelle Position des Spielers an den Server gesendet, dieser ließt die Informationen dann aus. <-- Soweit klappt alles, so wie ich es haben möchte.

Jetzt soll der Server aber in jeder Runde der Hauptschleife alle Types, also aller Spieler durchgehen (Dazu den Type player), die X/Y Position vom Type player dann an den Type client übergeben (Beide Types sollen also den gleichen Inhalt haben) und anschließend die X/Y Position an alle Verbunden Spieler senden (Dazu 2 Types, da ich es mit einem Type nicht hinbekommen habe).
Und dabei habe ich das Problem, damit wenn ich den ersten Client starte und danach noch einen zweiten, auf dem ersten Client der Spieler vopm zweiten Client gar nicht angezeigt wird und auf dem zweiten nur die Position vom ersten Client wo der Spieler stand, wo der zweite Client gestartet wurde.


Die CodeStelle:
Im Client, also im Spiel und in der Hauptschleife:
Code: [AUSKLAPPEN]
   ;Informationen jedes Spielers vom Server abfragen
   ReadServerTmp = ReadString(Server)

   If ReadServerTmp <> "" And ReadServerTmp <> 0 Then
   
      intype = 0 ;Zum prüfen, ob der Spieler bereits auf dem Client existiert
      
      ;Prüfen, ob UpdatePlayerID dabei seht
      p1 = Instr(ReadServerTmp, "UpdatePlayerID.")
      If p1 <> 0 Then
         ;Wenn ja, ID speichern
         playerID = Right(ReadServerTmp, Len(ReadServerTmp)-p1-14)
         
         ;Alle Spieler durchgehen
         For player = Each player
            ;Und prüfen, ob es der richtige Spieler ist
            If playerID = player\id Then
            
               ;Wenn ja, Type erneuern
               player\name = ReadString(Server)
               player\x = ReadString(Server)
               player\y = ReadString(Server)
                              
               intype = 1
            EndIf
         Next
         
         If update = 0 And playerID <> ID Then
            ;Wenn nichts gefunden wurde, neuen Spieler erstellen
            player = New player
            player\id = playerID
            player\name = ReadString(Server)
            player\x = ReadString(Server)
            player\y = ReadString(Server)
         EndIf
      EndIf
   EndIf

Dieser Code soll also, wenn der Server "UpdatePlayerID.player_id" sendet, alle Spieler wo der Client bereits kennt durchgehen, wenn der Spieler mit der ID dabei ist die Position verändern und ansonsten einen neuen Spieler (=neuer eintrag in den Type player) machen mit der ID/Name/PositionX/Y

Der ServerCode, wo die Informationen sendet:

Code: [AUSKLAPPEN]
For player = Each player
      ;Position der Anderen Spielern an den Client senden
      For client = Each client
         WriteString player\stream, "UpdatePlayerID."+client\id
         WriteString player\stream, client\name
         WriteString player\stream, client\x
         WriteString player\stream, client\y
      Next
Next

Diese Zeilen sind die einzigsten, die der Server bis jetzt sendet.

Ich hoffe, so ist mein Problem nun besser erklärt. (Hoffentlich nicht zu lang...)

ToeB

BeitragFr, Jun 27, 2008 22:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Kann es villeicht an ReadServerTmp leigen ? Das da nicht alle daten drinn sind ?

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

BadDeath

BeitragFr, Jun 27, 2008 23:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hatte auch letztens Startprobleme mit meinem Spiel Embarassed

Aber mit ein wenig Hilfe ging es wunderbar und bald werde ich nen WiP-Eintrag hier machen

Der Code war damals noch recht kurz und übersichtlich, evtl. hilft er dir weiter. du kannst mit dem auch mehrere clienten auf einem PC laufen lassen.

Im letzten Beitrag: https://www.blitzforum.de/foru...hp?t=28275 Laughing
 

Düsi

BeitragSa, Jun 28, 2008 11:33
Antworten mit Zitat
Benutzer-Profile anzeigen
BadDeath: So wie ich das nun verstanden habe, machst Du das mit UDP. - Ich wollts aber gerne mit TCP machen.

ToeB: Hm... Wie gemeint? Die Variable wurde bereits weiter obem im Code als String definiert. Oder wie meinst Du das?

Bzw. noch eine Anmerkung: Wenn ich mir im Client nun >player\name< ausgebe, erhalte ich >UpdatePlayer.player_id< ausgegeben, obwohl ich dies ja in einem ReadString zuvor schon auslese *verwirr*.

Ist es evtl. doch besser, das ganze mit UDP zu machen?

Hier einmal der ganze ServerCode:
Code: [AUSKLAPPEN]
;Bildschirm
Global screenx = 300
Global screeny = 200

Graphics screenx, screeny, 32, 2
SeedRnd MilliSecs
SetBuffer BackBuffer()
AppTitle "PanzerServer"


;Server erstellen
server = CreateTCPServer(8080)

;Prüfen, ob der Server erstellt wurde
If server <> 0 Then
   Print "Server wurde erstellt."
   WaitKey
Else
   Print "Server konnte nicht erstellt werden."
   WaitKey
   End
EndIf


;Variablen
   ;Timer
   Global timer
   
   ;Spiel
   Global players = 0
   
   ;Client-Server
   Global StreamTmp$
   Global Stream
   

;Grundeinstellungen
timer = CreateTimer(200)


;Types
Type player
   Field id ;ID
   Field stream ;Stream. - Wird zu empfangen&senden benötigt
   Field name$ ;Name
   Field x ;Für evtl. einen Check ab und zu
   Field y ;Too
End Type

Type client
   Field id
   Field stream
   Field name$
   Field x
   Field y
End Type

Global player.player
Global client.client

;Hauptschleife
Repeat
   Cls
   
   Locate 1, 1
   
   ;Prüfen, ob ein neuer Client Connectet
   Stream = AcceptTCPStream(Server)
   If Stream Then ;Wenn ja, neuer Type anlegen
      player = New player
      player\id = players
      player\stream = Stream
      
      client = New client
      client\id = players
      client\stream = Stream
      
      ;Die ID an den Client senden
      WriteString Stream, players ;Hier wird nur die ID gesendet, da dies als erstes vom Client
                           ;Abgefragt wird
      
      players = players + 1 ;Und die Spieleranzahl um 1 erhöhen
   EndIf    
      
   ;Alle Types durchgehen
   For player = Each player
   
      ;Prüfen, ob etwas gesendet wurde
      StreamTmp = ReadString(player\stream)
      If StreamTmp <> "" And StreamTmp <> 0 Then
         ;Wenn ja, auswerten!
         
         ;Name wechseln
         p1 = Instr(StreamTmp, "ChangeName.")
         If p1 <> 0 Then
            player\name = Right(StreamTmp, Len(StreamTmp)-p1-10)
         EndIf
         
         ;Position verändern
         ;X
         p1 = Instr(StreamTmp, "MoveX.")
         If p1 <> 0 Then
            player\x = Right(StreamTmp, Len(StreamTmp)-p1-5)
         EndIf
         ;Y
         p1 = Instr(StreamTmp, "MoveY.")
         If p1 <> 0 Then
            player\y = Right(StreamTmp, Len(StreamTmp)-p1-5)
         EndIf                         
      EndIf
      
      ;ServerAusgabe
      Print "Name: "+player\name
      Print "ID: "+player\id
      Print "X: "+player\x
      Print "Y: "+player\y
      
      
      ;Types abgleichen
      For client = Each client
         If client\id = player\id Then
            client\x = player\x
            client\y = player\y
         EndIf
      Next
      
      
      ;Position der Anderen Spielern an den Client senden
      For client = Each client
         WriteString player\stream, "UpdatePlayerID."+client\id
         WriteString player\stream, client\name
         WriteString player\stream, client\x
         WriteString player\stream, client\y
      Next    
   Next     

   
   Flip
   WaitTimer timer
Until KeyHit(1)
End


Und der ganze ClientCode, der etwas damit zu tun hat:

Code: [AUSKLAPPEN]
   ;Netzwerk
   Global NickName$ = "Düsi"
   Global ServerIP$ = "5.17.54.50"
   Global Port = 8080
   Global ID
   Global ReadServerTmp$
;Verbinden
Server = OpenTCPStream(ServerIP, Port)
If Server <> 0 Then   
   Print "Verbunden."
   WaitKey
Else
   Print "Verbindung fehlgeschlagen."
   WaitKey
   End
EndIf
;Grundinformationen an den Server Senden
   ;NickName
   WriteString Server, "ChangeName."+NickName
   
   ;Startposition
   WriteString Server, "MoveX."+panzerx
   WriteString Server, "MoveY."+panzery
   
;GrundInformationen vom Server abfragen
   ;ID
   ID = ReadString(Server)


;Types
Type player
   Field id
   Field name$
   Field x
   Field y
End Type

Global player.player

repeat
   ;Position an den Server senden
   WriteString Server, "MoveX."+panzerx
   WriteString Server, "MoveY."+panzery

   
   ;Alle MitSpieler malen
   For player = Each player
      ;Name Anzeigen
      Text player\x, player\y-20, player\name
      DrawImage panzer, player\x, player\y
   Next
   
   
   
   
   ;Informationen jedes Spielers vom Server abfragen
   ReadServerTmp = ReadString(Server)

   If ReadServerTmp <> "" And ReadServerTmp <> 0 Then
   
      intype = 0 ;Zum prüfen, ob der Spieler bereits auf dem Client existiert
      
      ;Prüfen, ob UpdatePlayerID dabei seht
      p1 = Instr(ReadServerTmp, "UpdatePlayerID.")
      If p1 <> 0 Then
         ;Wenn ja, ID speichern
         playerID = Right(ReadServerTmp, Len(ReadServerTmp)-p1-14)
         
         ;Alle Spieler durchgehen
         For player = Each player
            ;Und prüfen, ob es der richtige Spieler ist
            If playerID = player\id Then
            
               ;Wenn ja, Type erneuern
               player\name = ReadString(Server)
               player\x = ReadString(Server)
               player\y = ReadString(Server)
                              
               intype = 1
            EndIf
         Next
         
         If update = 0 And playerID <> ID Then
            ;Wenn nichts gefunden wurde, neuen Spieler erstellen
            player = New player
            player\id = playerID
            player\name = ReadString(Server)
            player\x = ReadString(Server)
            player\y = ReadString(Server)
         EndIf
      EndIf
   EndIf
until keyhit(1)
end

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group