Recent

Author Topic: how to make online game  (Read 13098 times)

shs

  • Sr. Member
  • ****
  • Posts: 310
how to make online game
« on: November 08, 2017, 11:45:51 am »
hi i want to make to make online game but i don't know how to start.
what protocol should i use? and how can i send the movement of the object? for example if i want to send message i can to sendstring but what can i use when making game?

firstly i just want to make a program where i can move a ball or any object with my keyboard and if client connects the server, the server's ball will be shown on client's screen and client can move client's ball which will be shown on the server's program.


Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #1 on: November 08, 2017, 12:50:58 pm »
Online games - are very complex thing, but core principle is simple.

TCP/IP protocol is usually used. UDP to send broadcast requests and locate clients, when playing on LAN. TCP/IP connection - is usually just a stream, similar to file stream. You can read from it and write to it - data format is arbitrary, as in case of files. IP address and port are used to identify every connection. Client can have only one such stream, while sever can have any number of such streams. Server usually listens some port. Client connects to this port, but when connection is accepted new unused port is allocated and assigned to this client, so every client has his unique connection. So, it's all about writing to connection, waiting for data to appear on connection and reading data from it.

How game itself works? You choose some framerate. Frame - is game time unit. 60 frames per second for example. Everything else is like in any other game - you read player's input and update state of your game on every frame. Only difference - parts of your game, like server and clients, have to send this state or update of this state to each other via network connections.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #2 on: November 08, 2017, 02:15:58 pm »
can show me an example code for this please?
Quote
How game itself works? You choose some framerate. Frame - is game time unit. 60 frames per second for example. Everything else is like in any other game - you read player's input and update state of your game on every frame. Only difference - parts of your game, like server and clients, have to send this state or update of this state to each other via network connections.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #3 on: November 08, 2017, 02:35:14 pm »
can show me an example code for this please?
Quote
How game itself works? You choose some framerate. Frame - is game time unit. 60 frames per second for example. Everything else is like in any other game - you read player's input and update state of your game on every frame. Only difference - parts of your game, like server and clients, have to send this state or update of this state to each other via network connections.
I don't have such code now and I don't have time to write an example today - may be tomorrow.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #4 on: November 08, 2017, 04:39:28 pm »
Finally, it works! Your "character" - is blue one. Frames per second = 30.

Server:
Code: Pascal  [Select][+][-]
  1. unit ServerMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Web.Win.Sockets, System.SyncObjs;
  8.  
  9. type
  10.   TCoords = record
  11.     X, Y:Integer;
  12.   end;
  13.   TForm1 = class(TForm)
  14.     TcpServer1: TTcpServer;
  15.     Timer1: TTimer;
  16.     Shape1: TShape;
  17.     Shape2: TShape;
  18.     procedure TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
  19.     procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  20.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  21.     procedure Timer1Timer(Sender: TObject);
  22.     procedure FormCreate(Sender: TObject);
  23.     procedure FormDestroy(Sender: TObject);
  24.   private
  25.     { Private declarations }
  26.   public
  27.     { Public declarations }
  28.     Sect:TCriticalSection;
  29.     ClientConnected:Boolean;
  30.     ClientCoords:TCoords;
  31.     Socket:TCustomIpClient;
  32.     Keys:array[Word] of Boolean;
  33.   end;
  34.  
  35. var
  36.   Form1: TForm1;
  37.  
  38. implementation
  39.  
  40. {$R *.dfm}
  41.  
  42. procedure TForm1.TcpServer1Accept(Sender: TObject;
  43.   ClientSocket: TCustomIpClient);
  44.   var Coords:TCoords;Data:Integer;
  45. begin
  46.   Sect.Acquire;
  47.   if ClientConnected then begin
  48.     Sect.Release;
  49.     Exit;
  50.   end;
  51.   Socket := ClientSocket;
  52.   ClientConnected := True;
  53.   Sect.Release;
  54.   Data := 0;
  55.   while Data >= 0 do begin
  56.     Data := ClientSocket.ReceiveBuf(Coords, SizeOf(Coords));
  57.     if Data = SizeOf(Coords) then begin
  58.       Sect.Acquire;
  59.       ClientCoords := Coords;
  60.       Sect.Release;
  61.     end;
  62.   end;
  63.   Sect.Acquire;
  64.   ClientConnected := False;
  65.   Socket := nil;
  66.   Sect.Release;
  67. end;
  68.  
  69. procedure TForm1.Timer1Timer(Sender: TObject);
  70.   var Coords:TCoords;
  71. begin
  72.   with Shape1 do begin
  73.     if Keys[VK_UP] then Top := Top - 2;
  74.     if Keys[VK_DOWN] then Top := Top + 2;
  75.     if Keys[VK_LEFT] then Left := Left - 2;
  76.     if Keys[VK_RIGHT] then Left := Left + 2;
  77.   end;
  78.   Sect.Acquire;
  79.   if ClientConnected then begin
  80.     Shape2.Visible := True;
  81.     Shape2.Left := ClientCoords.X;
  82.     Shape2.Top := ClientCoords.Y;
  83.     Coords.X := Shape1.Left;
  84.     Coords.Y := Shape1.Top;
  85.     Socket.SendBuf(Coords, SizeOf(Coords));
  86.   end
  87.   else begin
  88.     Shape2.Visible := False;
  89.   end;
  90.   Sect.Release;
  91. end;
  92.  
  93. procedure TForm1.FormCreate(Sender: TObject);
  94. begin
  95.   Sect := TCriticalSection.Create;
  96. end;
  97.  
  98. procedure TForm1.FormDestroy(Sender: TObject);
  99. begin
  100.   Sect.Destroy;
  101. end;
  102.  
  103. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  104.   Shift: TShiftState);
  105. begin
  106.   Keys[Key] := True;
  107. end;
  108.  
  109. procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  110. begin
  111.   Keys[Key] := False;
  112. end;
  113.  
  114. end.
  115.  

Client:
Code: Pascal  [Select][+][-]
  1. unit ClientMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Web.Win.Sockets;
  8.  
  9. type
  10.   TCoords = record
  11.     X, Y:Integer;
  12.   end;
  13.   TForm1 = class(TForm)
  14.     TcpClient1: TTcpClient;
  15.     Timer1: TTimer;
  16.     Shape1: TShape;
  17.     Shape2: TShape;
  18.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  19.     procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  20.     procedure Timer1Timer(Sender: TObject);
  21.   private
  22.     { Private declarations }
  23.   public
  24.     { Public declarations }
  25.     Keys:array[Word] of Boolean;
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.dfm}
  34.  
  35. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  36.   Shift: TShiftState);
  37. begin
  38.   Keys[Key] := True;
  39. end;
  40.  
  41. procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  42. begin
  43.   Keys[Key] := False;
  44. end;
  45.  
  46. procedure TForm1.Timer1Timer(Sender: TObject);
  47.   var Coords:TCoords;ReadReady, WriteReady, ExceptionHappened:Boolean;
  48. begin
  49.   with Shape1 do begin
  50.     if Keys[VK_UP] then Top := Top - 2;
  51.     if Keys[VK_DOWN] then Top := Top + 2;
  52.     if Keys[VK_LEFT] then Left := Left - 2;
  53.     if Keys[VK_RIGHT] then Left := Left + 2;
  54.   end;
  55.   if TcpClient1.Connected then begin
  56.     Shape2.Visible := True;
  57.     ReadReady := False;
  58.     WriteReady := False;
  59.     ExceptionHappened := False;
  60.     TcpClient1.Select(@ReadReady, @WriteReady, @ExceptionHappened);
  61.     if ReadReady then begin
  62.       if TcpClient1.ReceiveBuf(Coords, SizeOf(Coords)) = SizeOf(Coords) then begin
  63.         Shape2.Left := Coords.X;
  64.         Shape2.Top := Coords.Y;
  65.       end;
  66.     end;
  67.     if WriteReady then begin
  68.       Coords.X := Shape1.Left;
  69.       Coords.Y := Shape1.Top;
  70.       TcpClient1.SendBuf(Coords, SizeOf(Coords));
  71.     end;
  72.   end
  73.   else begin
  74.     Shape2.Visible := False;
  75.   end;
  76. end;
  77.  
  78. end.
  79.  
« Last Edit: November 08, 2017, 06:36:29 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #5 on: November 08, 2017, 10:30:11 pm »
Code: Pascal  [Select][+][-]
  1. uses
  2.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  3.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Web.Win.Sockets, System.SyncObjs;

why do you have something.something?
mine is just
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
do i have to copy your uses?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #6 on: November 08, 2017, 10:37:37 pm »
and where can i put ip address and port?

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #7 on: November 09, 2017, 05:08:17 am »
Code: Pascal  [Select][+][-]
  1. uses
  2.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  3.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Web.Win.Sockets, System.SyncObjs;

why do you have something.something?
mine is just
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
do i have to copy your uses?
and where can i put ip address and port?
Sorry, I've forgotten to mention it. It's Delphi code and I had no time yesterday to port it to Lazarus. Something.something - are namespaces and visual controls are used for TCP client and server, so IP address and port are set via object inspector. Unfortunately Lazarus doesn't have any visual networking library by default, so I needed to install something like Synapse or Indy first and I had no time. I just wanted to show general structure of application.
« Last Edit: November 09, 2017, 05:10:37 am by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #8 on: November 09, 2017, 11:09:52 am »
Code: Pascal  [Select][+][-]
  1.  sock.SendBuffer(Coords, SizeOf(Coords));    
when i try on lazarus
i get error message saying
unit1.pas(123,28) Error: Incompatible type for arg no. 1: Got "TCoords", expected "Pointer"

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #9 on: November 09, 2017, 11:41:23 am »
Code: Pascal  [Select][+][-]
  1.  sock.SendBuffer(Coords, SizeOf(Coords));    
when i try on lazarus
i get error message saying
unit1.pas(123,28) Error: Incompatible type for arg no. 1: Got "TCoords", expected "Pointer"
Try this:
Code: Pascal  [Select][+][-]
  1. sock.SendBuffer(@Coords, SizeOf(Coords));

I tried to port my examples to Lazarus, but unfortunately it isn't that simple: threads aren't implemented both in fcl-net and Synapse, so I have to do it myself and Indy is tricky to install. I.e. everything isn't as easy, as in Delphi. Delphi is called RAD for reason - because everything is rapid there.
« Last Edit: November 09, 2017, 11:42:56 am by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: how to make online game
« Reply #10 on: November 09, 2017, 12:56:27 pm »
Hey shs,

If you're really interested in game development, you should join the Pascal Game Development community.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #11 on: November 09, 2017, 12:58:21 pm »
the client can connect to the server but when the server moves its box it doesn't work on client program
*i only made 1 object on server just to check if the buffer is sent to the client
please check the attachment

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #12 on: November 09, 2017, 02:53:24 pm »
the client can connect to the server but when the server moves its box it doesn't work on client program
*i only made 1 object on server just to check if the buffer is sent to the client
please check the attachment
Remove canread(1000) from server's timer proc and it will work:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2.    var Coords:TCoords;
  3.      I: Integer;
  4. begin
  5.   Coords.X := Shape1.Left;
  6.   Coords.Y := Shape1.Top;
  7.   connections.SendBuffer(@Coords, SizeOf(Coords));
  8.  
  9.   with Shape1 do begin
  10.     if Keys[VK_UP] then Top := Top - 20;
  11.     if Keys[VK_DOWN] then Top := Top + 20;
  12.     if Keys[VK_LEFT] then Left := Left - 20;
  13.     if Keys[VK_RIGHT] then Left := Left + 20;
  14.   end;
  15. end;
  16.  
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to make online game
« Reply #13 on: November 09, 2017, 10:39:16 pm »
thank you :)
are there anything else i should fix or improve on?

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: how to make online game
« Reply #14 on: November 10, 2017, 07:00:53 am »
thank you :)
are there anything else i should fix or improve on?
I would use threads to avoid blocking main thread or using Application.ProcessMessages.

Also your server gets stuck in infinite message processing loop, so application can't be terminated (at least on Windows) - you should terminate this loop somehow. Something like this:
Code: Pascal  [Select][+][-]
  1. procedure TBoltzmannForm.Iterate;
  2.  var I, J:Integer; P, R, S:Int64;Id1, Id2:Integer;
  3. begin
  4.   P := 0;
  5.   SimulationProgressBar.Position := P;
  6.   Application.ProcessMessages;
  7.   for I := 0 to Iterations - 1 do begin
  8.     Id1 := Random(Count - 1);
  9.     while E[Id1] = 0 do begin
  10.       Id1 := Random(Count - 1);
  11.     end;
  12.     Id2 := Random(Count - 1);
  13.     while Id1 = Id2 do begin
  14.       Id2 := Random(Count - 1);
  15.     end;
  16.     Dec(E[Id1]);
  17.     Inc(E[Id2]);
  18.     R := (100 * (Int64(I) + 1)) div Iterations;
  19.     if R <> P then begin
  20.       P := R;
  21.       SimulationProgressBar.Position := P;
  22.       Application.ProcessMessages;
  23.     end;
  24.   end;
  25.   P := 0;
  26.   SimulationProgressBar.Position := P;
  27.   Application.ProcessMessages;
  28.   Probabilities.Clear;
  29.   Energies.Clear;
  30.   CalcProbabilities.Clear;
  31.   CalcEnergies.Clear;
  32.   for I := 0 to ShowCount - 1 do begin
  33.     S := 0;
  34.     for J := 0 to Count - 1 do begin
  35.       if E[J] = I then begin
  36.         Inc(S);
  37.       end;
  38.     end;
  39.     Probabilities.AddXY(I, S);
  40.     Energies.AddXY(I, S * I);
  41.     S := Trunc((Extended(Count) / Extended(Initial)) * Exp(-(Extended(I) / Extended(Initial))));
  42.     CalcProbabilities.AddXY(I, S);
  43.     S := Trunc((Extended(I) * (Extended(Count) / Extended(Initial))) * Exp(-(Extended(I) / Extended(Initial))));
  44.     CalcEnergies.AddXY(I, S);
  45.     R := (100 * (Int64(I) + 1)) div ShowCount;
  46.     if R <> P then begin
  47.       P := R;
  48.       SimulationProgressBar.Position := P;
  49.       Application.ProcessMessages;
  50.     end;
  51.   end;
  52. end;
  53.  
  54. procedure TBoltzmannForm.FormActivate(Sender: TObject);
  55. begin
  56.   while not Done do Iterate;
  57.   MessageDlg('Boltzmann distribution', 'Simulation stopped', mtInformation, [mbOK], 0);
  58. end;  
  59.  
  60. procedure TBoltzmannForm.FormClose(Sender: TObject;
  61.   var CloseAction: TCloseAction);
  62. begin
  63.   if not Done then begin
  64.     Done := True;
  65.     CloseAction := caNone;
  66.   end;
  67. end;
  68.  

Due to some reasons networking design is still obsoleted "active" one - i.e. you have to watch for everything yourself. It should have been kernel-driven "passive" event-based design for a long time already. Therefore every networking library have to implement such "passive" design. Most designs are very clunky. What we need - are just OnConnect, OnDisconnect and OnReceive events, synchronized with main message loop, and TStream to read and write data. That's it. As I know, Indy is the closest one to this "perfect" design, but it's very heavy and overcomplicated library.
« Last Edit: November 10, 2017, 07:05:18 am by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

 

TinyPortal © 2005-2018