Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi ping-pong->übermittlung (https://www.delphipraxis.net/45437-ping-pong-uebermittlung.html)

mangaka 6. Mai 2005 11:14


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 ^^
www.ludete.de/test.zip

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.

Blechwolf 6. Mai 2005 14:06

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

mangaka 6. Mai 2005 14:41

Re: ping-pong->übermittlung
 
stimmt das wäre ne idee...
aber ich habe kein plan wie ich das realisieren soll, haste ne idee?

Blechwolf 6. Mai 2005 15:05

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

mangaka 6. Mai 2005 15:28

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...

mangaka 6. Mai 2005 18:25

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.

Ultimator 6. Mai 2005 18:29

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...

starY 6. Mai 2005 18:44

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.

mangaka 6. Mai 2005 18:46

Re: ping-pong->übermittlung
 
Zitat:

Zitat von Ultimator
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 :?

habe ich nicht verstanden *g*

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---

mangaka 6. Mai 2005 18:51

Re: ping-pong->übermittlung
 
Zitat:

Zitat von starY
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.

vllt ne dumme frage:
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

starY 6. Mai 2005 19:00

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) ;)

mangaka 6. Mai 2005 19:06

Re: ping-pong->übermittlung
 
Zitat:

Zitat von starY
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) ;)

son sch*** aber auch..
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...

mangaka 7. Mai 2005 12:11

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?

DGL-luke 7. Mai 2005 12:25

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:
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;
senden:
Delphi-Quellcode:
client.socket.sendtext(s); //es gibt auhc noch sendstream und sendbuf
empfangen:
Delphi-Quellcode:
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;
:D

mangaka 7. Mai 2005 12:29

Re: ping-pong->übermittlung
 
Zitat:

Zitat von DGL-luke
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.
:D

hmm ich habe kein plan wie das ÜBERHAUPT geht ^^

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