![]() |
ping-pong->übermittlung
moin,
zurzeit programmiere ich das alt bekannte ping-pong game im netzwerk. immo arbeite ich am schläger ->bewege ich meinen schläger wird die position auf dem gegn. computer richtig angezeigt, nur die bewegung meines schlägers ist auf dem gegn.PC nicht zeitgleich mit der bewegung auf meinem pc. versteht ihr? also...: schläger(A) bewegt sich nicht so schnell auf pc(B) wie auf pc(A). jedoch ist die entgültige position von schläger(A) auf pc(B) richtig. ich geb euch ma den link zur .exe , dann könnt ihr es selbst aufprobieren und sehen was ich meine ^^ ![]() und hier nochma der code:
Delphi-Quellcode:
unit pingpongq;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer, IdIPWatch, IdSocketHandle, DXClass; type TForm1 = class(TForm) IdTCPClient1: TIdTCPClient; IdTCPServer1: TIdTCPServer; Edit1: TEdit; IdIPWatch1: TIdIPWatch; Label1: TLabel; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure IdTCPServer1Execute(AThread: TIdPeerThread); procedure Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure IdTCPClient1Connected(Sender: TObject); private LastStep: DWord; procedure Timer(Sender: TObject; var Done: Boolean); { Private declarations } public { Public declarations } end; var Form1: TForm1; y,p2top: Integer; p1_oben, p1_unten, senden_oben, senden_unten: Boolean; Player1, Player2: TImage; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var Binding: TIdSocketHandle;//Für die servereinstellungen begin //grafik: player1 Player1 := TImage.Create(Form1); Player1.Name := 'player1'; Player1.Parent := Form1; Player1.Top := 160; Player1.Left := 10; Player1.Picture.LoadFromFile('player1.bmp'); Player1.Visible := true; //grafik: player2 Player2 := TImage.Create(Form1); Player2.Name := 'player2'; Player2.Parent := Form1; Player2.Top := 160; Player2.Left := Form1.ClientWidth - 20; Player2.Picture.LoadFromFile('player2.bmp'); Player2.Visible := true; //server einstellen: IdTCPServer1.Bindings.Clear; Binding := IdTCPServer1.Bindings.Add; Binding.IP := idIPWatch1.LocalIP; Binding.Port := 9099; IDTCPServer1.Active := true; Application.OnIdle := Timer; DoubleBuffered := True; end; //zum gegn. server verbinden procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_Return then Begin IdTCPClient1.Host := Edit1.Text; IdTCPClient1.Port := 9099; IdTCPClient1.Connect; Edit1.Enabled := false; End; end; //client connected und gibt die posi vom eigenen schläger an procedure TForm1.IdTCPClient1Connected(Sender: TObject); begin IdTCPClient1.WriteLn('160'); end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_Space then Begin End; {p1_oben/p1_unten bewegen den eigenen schläger mit hilfe von senden_oben/senden_unten senden wir unsere posi} if Key = VK_UP then Begin p1_oben := true; senden_oben := true; End; if Key = VK_Down then Begin p1_unten := true; senden_unten := true; End; end; //hört mit den obigen aktionen auf procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_UP then Begin p1_oben := false; senden_oben := false; End; if Key = VK_Down then Begin p1_unten := false; senden_unten := false; End; end; {server nimmt gegn. nachricht auf und verarbeitet sie zu der posi vom gegn. schläger} procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); var empfangen: String; begin while Form1.IdTCPClient1.Connected do Begin empfangen := AThread.Connection.ReadLn; p2top := StrToInt(empfangen); Player2.Top := p2top; End; end; {application.onIdle event fungiert als timer: entstehung und übermittlung der eigenen bewegung} procedure TForm1.Timer(Sender: TObject; var Done: Boolean); begin Done:=false; If GetTickCount-LastStep > 10 then //in 10ms ein schritt Begin y := 7; if (p1_oben) and (Player1.Top > 11) then Player1.Top := Player1.Top - y; if (p1_unten) and (Player1.Top < 379) then Player1.Top := Player1.Top + y; Label1.Caption := IntToStr(Player1.Top); if IdTCPClient1.Connected then Begin if senden_oben then IdTCPClient1.WriteLn(IntToStr(Player1.Top)); if senden_unten then IdTCPClient1.WriteLn(IntToStr(Player1.Top)); End; Label2.Caption := IntToStr(Player2.Top); LastStep:= GetTickCount; //neue Start Zeit end; end; end. |
Re: ping-pong->übermittlung
Hm, würde jetzt mal spontan auf sowas wie Netzwerk-Overhead tippen...
Erste Idee wäre jetzt ne Synchronisation einzubauen. Also Daten an PC2 schicken, PC2 schickt zurück das die Sachen angekommen sind und dann erst zeichnest Du das ganze auch auf PC1. Allerdings dürfte dabei dann die Bewegung von Schläger 1 auf PC 1 langsamer werden. Grüße Wolf |
Re: ping-pong->übermittlung
stimmt das wäre ne idee...
aber ich habe kein plan wie ich das realisieren soll, haste ne idee? |
Re: ping-pong->übermittlung
Naja, wenn Daten bei PC2 ankommen, abfragen ob es ne Positions-übermittlung ist und wenn ja dann direkt ein "Bekommen" zurück schicken.
Hab aber keine Ahnung ob TIdIPWatch sowas hergibt. Aber letztlich müsstest Du da doch auch abfragen können, ob was rein kommt. Hab mich noch nicht wirklich mit der Technischen Seite befasst. Schönes WE |
Re: ping-pong->übermittlung
ja also ich habe ein bissl rumgearbeitet und habe es jetzt synchron...
aber jetzt sieht das alles so rucklig aus, vorher sah nur der gegn. player so aus. wäre natürlich toll würde alles flüssig laufen... |
Re: ping-pong->übermittlung
das ist der neue code und es ist immernoch nicht synchron:
ich habs versucht die posi des schlägers schon vorher zu senden, aber es geht nicht... das beste wäre es ich benutze nanosekunden, aber wenn ich da 1/10000000 hinschreibe ändert sich nicht wirklich was. meine vermutung -> es geht nicht mit nanosek. ^^ vllt habt ihr noch ne idee
Code:
unit pp_mpq;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdSocketHandle, StdCtrls, IdIPWatch, IdTCPServer, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, ExtCtrls; type TForm1 = class(TForm) IdTCPClient1: TIdTCPClient; IdTCPServer1: TIdTCPServer; IdIPWatch1: TIdIPWatch; Edit1: TEdit; Label1: TLabel; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure IdTCPServer1Execute(AThread: TIdPeerThread); procedure FormClose(Sender: TObject; var Action: TCloseAction); private Zeit_1: DWord; Zeit_2: DWord; procedure Timer(Sender: TObject; var Done: Boolean); { Private declarations } public { Public declarations } end; var Form1: TForm1; Player1, Player2: TImage; p1_oben, p1_unten: Boolean; p2_top: Integer; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var Binding: TIdSocketHandle; begin p1_oben := false; p1_unten := false; p2_top := 160; Application.OnIdle := Timer; DoubleBuffered := True; //server einstellen: IdTCPServer1.Bindings.Clear; Binding := IdTCPServer1.Bindings.Add; Binding.IP := idIPWatch1.LocalIP; Binding.Port := 9099; IDTCPServer1.Active := true; // //grafik: player1 Player1 := TImage.Create(Form1); Player1.Name := 'player1'; Player1.Parent := Form1; Player1.Top := 160; Player1.Left := 10; Player1.Picture.LoadFromFile('player1.bmp'); Player1.Visible := true; //grafik: player2 Player2 := TImage.Create(Form1); Player2.Name := 'player2'; Player2.Parent := Form1; Player2.Top := 160; Player2.Left := Form1.ClientWidth - 20; Player2.Picture.LoadFromFile('player2.bmp'); Player2.Visible := true; end; //zum gegn. server verbinden procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_Return then Begin IdTCPClient1.Host := Edit1.Text; IdTCPClient1.Port := 9099; IdTCPClient1.Connect; Edit1.Enabled := false; End; end; //hört mit den obigen aktionen auf procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin {p1_oben/p1_unten bewegen den eigenen schläger mit hilfe von senden_oben/senden_unten senden wir unsere posi} if Key = VK_UP then Begin p1_oben := true; End; if Key = VK_Down then Begin p1_unten := true; End; end; procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); begin while Form1.IdTCPClient1.Connected do Begin p2_top := StrToInt(AThread.Connection.ReadLn); End; end; procedure TForm1.Timer(Sender: TObject; var Done: Boolean); begin Done:=false; If GetTickCount - Zeit_1 > 10 then //in 10ms ein schritt Begin if (p1_oben) and (Player1.Top > 11) then Begin Player1.Top := Player1.Top - 7; p1_oben := false; End; if (p1_unten) and (Player1.Top < 379) then Begin Player1.Top := Player1.Top + 7; p1_unten := false; End; Label1.Caption := IntToStr(Player1.Top); Label2.Caption := IntToStr(Player2.Top); Zeit_1:= GetTickCount; //neue Start Zeit ermitteln End; if GetTickCount - Zeit_2 > 1 then Begin if IdTCPClient1.Connected then IdTCPClient1.Writeln(IntToStr(Player1.Top)); Player2.Top := p2_top; Zeit_2 := GetTickCount; End; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin IdTCPClient1.Disconnect; end; end. |
Re: ping-pong->übermittlung
Da der Timer eine Auflösung von ~20ms hat, erreichst du höchstens eine Framerate von 1000ms/20ms = 50 FPS, was allerdings kein Ruckeln hervorruft :?
Es kann aber sein, dass die Indy "zu langsam" sind, die Daten zu versenden. Evtl. liegt das ja auch an deiner Internetgeschwindigkeit? Oder du sendest einfach zu viele Daten... |
Re: ping-pong->übermittlung
Ich würde darauf Tippen, dass die Indy Komponenten zu langsam sind und du mit Sockets Arbeiten solltest. Ausserdem muss deine Ping auch bei 20 msec liegen wegen dem Timer sonst hängt, dass Spiel immer hinterher. Ich würde "nur" alle 80 msec übertragen lassen. Kommt nun drauf an was für einen Rechner du hast und wie schnell sich der Ball bewegen soll.
|
Re: ping-pong->übermittlung
Zitat:
hmm..aber ich kann nur indy nutzen, weil nur das habe und mich nur damit auskenne. und warum sollte ich zuviele daten senden? ich sende nur eine sache und das ist die posi vom dem player. und nicht nur übers internet ist das so sondern auch über lan, das ist das dumme ja. wenn ich aber auf meinen eigene rechner verbinde dann läuft alles flüßig. naja das könnte auch nen hinweis auf die datengeschwindigkeit sein.. ---bin am verzweifeln--- |
Re: ping-pong->übermittlung
Zitat:
meinste mit sockets die standart dinger von borland? wenn ja -hab ich ja schon erwähnt- habe ich die nicht. oder meinste solche socket-dinger von indy/ für indy????(kenn mich bei indy nun auch nicht soo aus^^) sry für meine ausdrucksweise :) bei zuvielen ms sieht das schrecklich aus, richtig richtig schwerfällig das ganze->das ist auch nicht das wahre |
Re: ping-pong->übermittlung
Die Standardteile von Borland ja^^ WinSockets halt ;) Die Indys sind für derart schnelle Dateiübertragung nicht gemacht. Sonst übermittel doch nur wann die Keys losgelassen werden, da wohl kaum einer kürzer als 100 msec drücken kann sollte das wohl besser gehen. (denke ich zumindest korrigiert mich wenn ich falsch liege) ;)
|
Re: ping-pong->übermittlung
Zitat:
tja ich habe das grad mit den msec getestet: habe die bewegung des eigenen schlägers auf 130 gestellt und die übertragung auf 100 aber trozdem ging das nicht... man kann die leute von borland nur liebhaben ...warum zum teufel haben die denn die winsockets bei der d7pe version rausgenommen... habe noch delphi3 pro aber da gibts keine winsockets odeR? das mit den keys habe ich auch schon versucht, nur weis ich grad nicht ob das ging...^^(habe zuviele versuche und veränderungen unternommen/durchgenommen) echt zum heulen... |
Re: ping-pong->übermittlung
da ich jetzt mit indy nicht weiter komme, möchte ich dies sockets zur laufzeit erzeugen.
aber es gibt da ein problem: ich habe kein plan wie, wenn ich die sockets erstellt habe, benutzen soll, da ich mit den sockets einfach nicht auskenne. gibts irgendwie referenzseite dazu? |
Re: ping-pong->übermittlung
du kannst die sockets aber registrieren.
die winsocks unit einfach in ein package machen und dann installieren. geht bei d2005pe mit fünf klicks und du hast sie in der toolbox. ich habe das allerdings bei d7pe auch irgendwie hingekriegt. winsocks verwenden: init:
Delphi-Quellcode:
senden:
server:=TWinServerSocket.create;
client:=TWinCLientSocket.create; server.port:=6667; //das is der standard IM port. kannst auch nen anderen nehmen, aber glaub ich besser nicht unter 1000 client.port:=6667; //ebenso client.address:='127.0.0.1' //die loopback ip. hier die des entfernten rechners nehmen. oder lassen, wenn dus auf deinem eigenen rechner probieren willst. server.open(); //()?! verdammt ich mach eindeutig zu viel mit c und java.... client.open;
Delphi-Quellcode:
empfangen:
client.socket.sendtext(s); //es gibt auhc noch sendstream und sendbuf
Delphi-Quellcode:
:D
procedure TForm1.RegServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket); //ereignisbehandlung für server.onclientread!!!!! //ich weiss nicht, was man da genau reinschreeiben muss..... //EDIT: doch ich glaub es geht so: begin s:=server.socket.receivetext; //analog receivebuffer end; |
Re: ping-pong->übermittlung
Zitat:
aber danke für deine Hilfe! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz