Seite 1 von 1

Synchronisieren!

Verfasst: 18.01.2008 23:57
von Milchshake
Hi,
ich habe ein Problem.
Server:

Code: Alles auswählen

InitNetwork()
InitKeyboard()
InitSound()
InitSprite()

Structure Client
  x.w
  y.w
  Id.w
  State.w
EndStructure
Global NewList Client.Client()

If OpenWindow(0,0,0,410,310,"Tastatur Test",#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0),5,5,320,300,0,0,0)
     CreateSprite(0,20,20)
     StartDrawing(SpriteOutput(0))
     Box(0,0,20,20,#White)
     StopDrawing()
     

    EndIf
  EndIf
  Buffer = AllocateMemory(1000)
  CreateNetworkServer(0,6666)
  Repeat
  FlipBuffers()
  ExamineKeyboard()
  ClearScreen(0)
  FreeMemory(Buffer)
  Buffer = AllocateMemory(1000)
  
  
  Event.l = WindowEvent()
  
  StartDrawing(ScreenOutput())
    DrawingMode(1)
   If Sent = 0
    DrawText(100,100,"Nichts gedrückt",#White)
   EndIf 
   If Sent = 2
    DrawText(100,100,"Rechts gedrückt",#White)
   EndIf 
   If Sent = 4
    DrawText(100,100,"Links gedrückt",#White)
   EndIf 
   DrawText(0,0,"PosX: "+Str(PosX),#White)
   DrawText(0,20,"PosY: "+Str(PosY),#White)
   StopDrawing()
   
   ;-Moving

   
   Client = EventClient()
   Server = NetworkServerEvent() 
   
   Select Server
   Case 1
   Start = 1
   Case 2 
   ReceiveNetworkData(EventClient(),Buffer,1000)
   Sent = PeekQ(Buffer)
   Case 4
   PosX = 0
   PosY = 0
   EndSelect 
   
   If Sent = 2
   PosX + 2
   EndIf 
   If Sent = 4
   PosX - 2
   EndIf 
  
  
  Until KeyboardPushed(#PB_Key_Escape) Or Event = #PB_Event_CloseWindow 
Client:

Code: Alles auswählen

InitNetwork()
InitKeyboard()
InitSound()
InitSprite()

Structure Client
  x.w
  y.w
  Id.w
  State.w
EndStructure
Global NewList Client.Client()

If OpenWindow(0,0,0,410,310,"Tastatur Test",#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0),5,5,320,300,0,0,0)
     CreateSprite(0,20,20)
     StartDrawing(SpriteOutput(0))
     Box(0,0,20,20,#White)
     StopDrawing()
     

    EndIf
  EndIf
  Buffer = AllocateMemory(1000)
  Server = OpenNetworkConnection("127.0.0.1",6666)
  Repeat
  FlipBuffers()
  ExamineKeyboard()
  ClearScreen(0)
  FreeMemory(Buffer)
  DisplaySprite(0,PosX,PosY)
  Buffer = AllocateMemory(1000)
  
  Event.l = WindowEvent()
  Old = Sent

   
   If KeyboardPushed(#PB_Key_Right) 
   Sent = 2
   PokeQ(Buffer,Sent)
   PosX + 2
   EndIf 
   
   If KeyboardPushed(#PB_Key_Left) 
   Sent = 4
   PokeQ(Buffer,Sent)
   PosX - 2
   EndIf 

   
   If KeyboardReleased(#PB_Key_All)
   Sent = 0
   PokeQ(Buffer,Sent)
  
   EndIf 
   
   StartDrawing(ScreenOutput())
    DrawingMode(1)
   If Sent = 0
    DrawText(100,100,"Nichts gedrückt",#White)
   EndIf 
   If Sent = 2
    DrawText(100,100,"Rechts gedrückt",#White)
   EndIf 
   If Sent = 4
    DrawText(100,100,"Links gedrückt",#White)
   EndIf 
   DrawText(0,0,"Sent: "+Str(Sent),#White)
   DrawText(0,20,"Old: "+Str(Old),#White)
   StopDrawing() 
   
   Client = EventClient()

   If Sent <> Old
   SendNetworkData(Server,Buffer,1000)
   EndIf 
   
  

  
  Until KeyboardPushed(#PB_Key_Escape) Or Event = #PB_Event_CloseWindow 
Wenn man jetzt einmal in des Linke Eck fähr, und nachher in das Rechte Eck, ist die PosX nicht mehr null, wie es eig. sein sollte.

Wie kann ich das besser machen, bzw. Synchronisieren?

lg Milchshake

Verfasst: 19.01.2008 00:06
von STARGÅTE
ab und zu "Positionssynkronisation durchführen"

zB.
1.
der Server senden die Position (die auf meinem Bildschirm angezeigt wird) an alle Clienten die dann ihre anpassen.

2.
Alle Clienten senden Tichproben Artig ihre Daten an den Server, dieser ermittelt eine Durchschnittsprosition und sendet diese wieder zurück. (dann kommt es weniger zu sprüngen)

Aber diese Positionssynkronisation soll halt immer nu manchal gemacht werden.
Habe jetzt kein Wert parat, aber wenns nur wenig Daten sind kannst du ja mal ein Intervall von 2s probieren
Wenns mehr daten sind, zerlege sie und sende sie stückchenweise alle 2s oder so

Verfasst: 19.01.2008 00:18
von hardfalcon
Bis jetzt konnte ich nur Synchronisierungsprobleme feststellen, wenn man beide beide Pfeiltasten gleichzeitig drückt. Das weisse Rechteck bewegt sich nicht, aber die Koordinaten im Serverfenster verändern sich weiter.

Versuch nicht Tastendrücke zu übertragen (spätestens bei Spielen übers Internet wird es sonst ziemlich kaeln und ruckeln), sondern übertrag einfach die absolute Position.

Verfasst: 19.01.2008 02:02
von ZeHa
@ Milchshake:
Du wolltest mein Network Pong haben, ich hab's mal hier veröffentlicht:
http://www.purebasic.fr/german/viewtopic.php?p=184141

Verfasst: 19.01.2008 12:13
von Milchshake
Die absolute Position habe ich schon einmal Probiert abzufragen, doch da ruckelt es noch mehr.
Sieh hier:
http://www.purebasic.fr/german/viewtopic.php?t=15431

Da ruckelte der Server noch viel mehr, als er es jetzt tut.

Oder meinst du das anderst mit der absoluten Position?

Verfasst: 19.01.2008 13:07
von ZeHa
Mach's mit Dead Reckoning, das ist letztendlich die beste Methode, weil Du eben in die "Zukunft" schauen kannst. Du mußt nur einige Dinge eben ein bißchen "glätten" durch Interpolieren und Dir überlegen, welche der beiden Seiten über wichtige Dinge wie Kollisionen etc. entscheiden darf.

Verfasst: 19.01.2008 14:51
von Milchshake
Argh!!
Ich schaffe es einfach nicht, mich in das Dead Reckoning einzulesen...
:|
Kannst du mir bitte mal einen kurzen Beispielcode machen, so in der Art wie
der von mir?

Danke :mrgreen:

Verfasst: 19.01.2008 15:59
von ZeHa
Naja Du mußt einfach das Prinzip verstanden haben, gibt auch im Internet einige Artikel darüber.

Das Prinzip ist folgendes:
Wenn Du etwas übers Internet verschickst, kommt es beim Empfänger oft erst nach 200 ms an. Also wird als erstes dieser Zeitunterschied ermittelt und dann sozusagen die "Uhren" gleichgestellt. Somit arbeiten beide Rechner in der Hauptschleife mit der exakt selben Zeit, weil der Server sich einfach die Zeit durch ElapsedMilliSeconds() holt, der Client macht es genauso aber rechnet die Zahl entsprechend um, sodaß auch bei ihm die gleiche Zeit herrscht.

Nun sind alle Funktionen wie getX() und getY() so programmiert, daß sie einem die Position immer zu einem bestimmten Zeitpunkt liefern können, indem sie einfach die zuletzt sicher bekannte Position nehmen, dazu auch die passende Zeit besitzen, und dann anhand der Bewegungsrichtung und -geschwindigkeit einfach die aktuelle Position (oder besser: die Position zum gewünschten Zeitpunkt) ausrechnen. Bei den ganzen Kollisionsabfragen wird dann eben immer die aktuelle Zeit übergeben, und die ist ja bei beiden gleich. Somit liefern beide theoretisch die gleichen Ergebnisse - nur dann nicht, wenn gerade eine der beiden Seiten einen Richtungswechsel vollzogen hat. Dort wird sich das Objekt auf dem jeweils anderen Rechner noch 200 ms lang in die alte Richtung bewegen, aber sobald dann der Richtungswechsel angekommen ist, stimmt die Sache wieder.

Nun kommt die große Kunst, nämlich diese Fehler durch Interpolieren irgendwie auszugleichen, sodaß sich die Position eines Objekts nicht ruckartig ändert, sobald das Update übers Netzwerk ankommt. Und da bin ich selbst noch nicht allzu weit gekommen. Aber wie gesagt, darüber gibt's auch ein paar Artikel im Netz, einfach mal googlen.

Verfasst: 19.01.2008 16:05
von ZeHa
Ach ja, natürlich sollte man noch UDP benutzen und nicht TCP, um die Latenz noch weiter zu verringern. Problem ist nur, daß UDP über PB bei mir nicht zu funktionieren scheint, ich weiß allerdings nicht, warum.