Page 1 of 1

Help with network game

Posted: Fri Jan 28, 2005 1:27 pm
by DriakTravo
I am working on a game that can be played over the network and I was wondering how the computers would communicate with each other. I know how to program all the networking commands, I am just wondering how the computers commuicate to each other.

Posted: Fri Jan 28, 2005 3:10 pm
by dracflamloc
I wrote an example of a 2-player network "game" for z3phir, it may have what you are looking for.

Otherwise a good bet would be to just combine the example source codes of server, and client, with the sprite commands.

Code: Select all

;*****************************************************************
; Multiplayer 2d Game Example
; Copyright 2005 DracSoft
; www.dracsoft.com
; Feel free to use this code in any application for any reason.
; I know its ugly but its just for learning purposes.
;*****************************************************************


;variables for example
Global Player1X.l
Global Player2X.l
Global Player1Y.l
Global Player2Y.l
Global isServer.b
Port.l
IP.s
connID.l
Buffer = AllocateMemory(1000)
Screen.l

;Procedures
Procedure HandleData(dataString.s)
  x=Val(StringField(dataString,1,","))
  y=Val(StringField(dataString,2,","))
  
  If isServer
    Player1X=x
    Player1Y=y
  Else
    Player2X=x
    Player2Y=y
  EndIf
EndProcedure

Procedure DrawScreen()
  ClearScreen(255,255,255)
  StartDrawing(ScreenOutput())
  Locate(Player1X,Player1Y)
  DrawText("1")
  Locate(Player2X,Player2Y)
  DrawText("2")
  StopDrawing()
  FlipBuffers()
EndProcedure


;get initial data
OpenConsole()
PrintN("Enter 1 for Server, 2 for Client:")
in.s=Input()
PrintN("Enter the port: ")
Port.l=Val(Input())
If in="1"
  isServer=#True 
Else
  isServer=#False 
  PrintN("Enter the IP to connect to: ")
  IP = Input()
EndIf
PrintN("")
CloseConsole()


;start 2d screen and initialize keyboard
InitSprite()
Screen=OpenWindow(#PB_Any,1,1,640,480,#PB_Window_TitleBar,"MP 2D Test")
OpenWindowedScreen(WindowID(Screen),1,1,640,480,#False,0,0)
doQuit.b=0
InitKeyboard()
If InitNetwork()=0 
  doQuit=1
EndIf


If isServer
  
  ;Do server operations
  CreateNetworkServer(Port)
  
  While doQuit=0 
    tmp=WindowEvent()
    event=NetworkServerEvent()
    If event=2  ;data arrival
      connID=NetworkClientID()
      
      tmps.s=""
      While CountString(tmps,"|")=0
        ReceiveNetworkData(connID,Buffer,1000)
        tmps=tmps+PeekS(Buffer)
      Wend
      
      HandleData(tmps)
    ElseIf event=1  ;new connection
      connID=NetworkClientID()
      ;MessageRequester("","Client connected.")
    EndIf
    
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Left)
      Player2X=Player2X-1
      SendNetworkString(connID,Str(Player2X)+","+Str(Player2Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Right)
      Player2X=Player2X+1
      SendNetworkString(connID,Str(Player2X)+","+Str(Player2Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Up)
      Player2Y=Player2Y-1
      SendNetworkString(connID,Str(Player2X)+","+Str(Player2Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Down)
      Player2Y=Player2Y+1
      SendNetworkString(connID,Str(Player2X)+","+Str(Player2Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Escape)
      doQuit=1
    EndIf
    
    DrawScreen()
  Wend
   
Else
  
  ;Do client operations
  connID=OpenNetworkConnection(IP,Port)
  If connID=#Null
    MessageRequester("Error","Couldn't connect.")
    doQuit=1
  EndIf 
  
  While doQuit=0  
    tmp=WindowEvent()
    
    event=NetworkClientEvent(connID)
    If event=2
      tmps.s=""
      While CountString(tmps,"|")=0
        ReceiveNetworkData(connID,Buffer,1000)
        tmps=tmps+PeekS(Buffer)
      Wend
      HandleData(tmps)
    EndIf
    
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Left)
      Player1X=Player1X-1
      SendNetworkString(connID,Str(Player1X)+","+Str(Player1Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Right)
      Player1X=Player1X+1
      SendNetworkString(connID,Str(Player1X)+","+Str(Player1Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Up)
      Player1Y=Player1Y-1
      SendNetworkString(connID,Str(Player1X)+","+Str(Player1Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Down)
      Player1Y=Player1Y+1
      SendNetworkString(connID,Str(Player1X)+","+Str(Player1Y)+"|")
    ElseIf KeyboardPushed(#PB_Key_Escape)
      doQuit=1
    EndIf
    
    DrawScreen()
  Wend
  
EndIf


;Quit
If isServer
  CloseNetworkServer()
Else
  CloseNetworkConnection(connID)
EndIf

Posted: Fri Jan 28, 2005 5:04 pm
by DriakTravo
Oh, I kind of understand now, I was acually making a file on each of the clients computers and sending it to the server. Then the server sends it to the rest of the computers and each client reads the file and updates the screen. But this looks alot faster. I will try making my game again if I have any questions, I will post them here. Thanks for helping.

EDIT: Is there a way to find servers on the network? Like instead of entering the IP everytime?

Posted: Fri Jan 28, 2005 7:05 pm
by DriakTravo
OK, in the example above, you showed me how a client can communicate with a server and a server can communicate with a client. But how can a client send data to another client. or lets say you have 3 clients, how can they send each others data to each other?

Any help would be helpful, thanks.

Posted: Fri Jan 28, 2005 8:07 pm
by olejr
Probably through the server..
You send a message marked as "broadcast" from one client to the server, and the server see it like that, and sends this to all other clients...

btw: i didn't read the code posted earlier, but this is the way it's done when you work with client - server..

Posted: Fri Jan 28, 2005 8:45 pm
by dracflamloc
Yes you'll need to send a message tot he server and have part of that message specify which client to forward the message to.

It's impossible to send a message client to client unless you are using connectionless networking such as UDP, which I do not think PB supports natively at this point. You could always use API however.

Posted: Fri Jan 28, 2005 8:47 pm
by DriakTravo
okay, so I send the data throgh the server to all the other clients. Does anyone have a code snipet to show me how to do this? I tried something like this:

Code: Select all

Repeat
  Sevent = NetworkServerEvent()
  If Sevent
    ClientID = NetworkClientID()
    If numberofplayers = 0
      numberofplayers = 1
      player1ID = NetworkClientID()
    Else
      player2ID = NetworkClientID()
    EndIf
    Select Sevent
      Case 1
        PrintN("Someone has connected!")
      Case 2
        ReceiveNetworkData(ClientID,Buffer,1000) 
        If NetworkClientID() = player1ID
          SendNetworkString(player2ID,PeekS(Buffer))
        EndIf
        If NetworkClientID() = player2ID
          SendNetworkString(player1ID,PeekS(Buffer))
        EndIf
        buffer = AllocateMemory(1,1000)
      Case 4
        PrintN("Someone disconnected!")
    EndSelect
  EndIf
Where the server gets the ClientID of the Clients and then whenever a client sends information to the server, it sends it to the other one. But this didn't seem to work. does anyone know what I am doing wrong?

Posted: Fri Jan 28, 2005 11:39 pm
by DriakTravo
alright, here is my code. It is basically a modified version of the code you gave me. one of the computers responds and the other one doesnt work at all. The one that responds is very inacurate and choppy. please help

Code: Select all

InitNetwork()
InitKeyboard()
InitMouse()
InitSprite()

Player1X.l
Player1Y.l
Player1MX.l
Player1MY.l
Player1C.l

Player2X.l
Player2Y.l
Player2MX.l
Player2MY.l
Player2C.l

isserver.b
port.l = 6832
Buffer = AllocateMemory(1,10000)

OpenConsole()
PrintN(">>> T A N K - B U S T E R <<<")
PrintN("[1]Player1 [2]Player2")
Print(">")
selection.s = Input()
If selection = "1"
  isServer = #true
ElseIf selection = "2"
  isServer = #false
Else
  End
EndIf

If isServer
  CreateNetworkServer(port)
  ClearConsole()
  PrintN(">>> T A N K - B U S T E R <<<")
  ExamineIPAddresses()
  PrintN("IP: "+IPString(NextIPAddress()))
  Print("Waiting for player 2")

  Repeat
    Sevent = NetworkServerEvent()
    If sevent
      Select sevent
        Case 1
          startgame = 2
      EndSelect
    EndIf
  Until startgame = 2
  CloseConsole()
Else
  ClearConsole()
  PrintN(">>> T A N K - B U S T E R <<<")
  Print("IP: ")
  ip.s = Input()
  player2id = OpenNetworkConnection(ip, Port)
  If player2id
    beep_(1000,200)
    beep_(2000,200)
  Else
    beep_(2000,200)
    beep_(1000,200)
    End
  EndIf
  CloseConsole()
EndIf

OpenScreen(800,600,16,"Tank Buster")

player1x = 50
player1y = 50

player2x = 350
player2y = 350

TransparentSpriteColor(-1,255,0,255)
ClearScreen(255,0,0)
CreateSprite(0,50,50)
CreateSprite(1,50,50)

If isServer
  Repeat
    ClearScreen(0,60,0)
      DisplayTransparentSprite(0,player1x,player1y)
      DisplayTransparentSprite(1,player2x,player2y)
    FlipBuffers()
    
    sevent = NetworkServerEvent()
    If sevent = 2
      temp.s = ""
      clientid = NetworkClientID()
      ReceiveNetworkData(clientid, buffer, 10000) 
      temp = PeekS(buffer)
      buffer = AllocateMemory(1,10000)
      player2x=Val(StringField(temp,1,",")) 
      player2y=Val(StringField(temp,2,",")) 
    EndIf
    
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Up)
      player1y - 3
      SendNetworkString(clientid,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_Down)
      player1y + 3
      SendNetworkString(clientid,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_left)
      player1x - 3
      SendNetworkString(clientid,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_right)
      player1x + 3
      SendNetworkString(clientid,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_escape)
      End
    EndIf 

  ForEver
Else
;- clientcode
  Repeat
    ClearScreen(0,60,0)
      DisplayTransparentSprite(0,player1x,player1y)
      DisplayTransparentSprite(1,player2x,player2y)
    FlipBuffers()
    
    sevent = NetworkServerEvent()
    If sevent
      If sevent = 2
        temp.s = ""
        ReceiveNetworkData(player2id, buffer, 10000) 
        temp = PeekS(buffer)
        buffer = AllocateMemory(1,10000)
        player2x=Val(StringField(temp,1,",")) 
        player2y=Val(StringField(temp,2,","))
      EndIf
    EndIf
    
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Up)
      player1y - 3
      SendNetworkString(player2id ,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_Down)
      player1y + 3
      SendNetworkString(player2id ,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_left)
      player1x - 3
      SendNetworkString(player2id ,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_right)
      player1x + 3
      SendNetworkString(player2id ,Str(player1x)+","+Str(player1y))
    EndIf
    If KeyboardPushed(#PB_Key_escape)
      End
    EndIf
  ForEver
EndIf



















Posted: Sun Jan 30, 2005 12:21 pm
by DriakTravo
okay, how would I send data that the server has to all the clients connected to the network?

Posted: Sun Jan 30, 2005 12:43 pm
by olejr
Well I will try to explain..

When a client send a message, it has to include things like this:
ClientID, MessageType(example '255') and the message itself..

And when the server get this message it does something like this:
msgtype = ParseMsg()
Select MsgType
Case msgtype
DoThis()
Case msgtype
DoThat()
; and so on..
EndSelect

So lets say "255" mean BroadcastToAll.
The server then has a list of all connected clients,
and sends the message to everyone,
excluding the one that sent the message.. (no need to get what you just sent right back is it(!)..)

When that's said I think that this kind of thing should be done with UDP, and not TCP..
But then again there's no 'internal' UDP support in PB.

But if you know some API there's really not that hard to get UDP working..

Not very clear, but I hope you get some of it.. :?

EDIT: And then I re-read youre post..
You can store all connected client ids in for example a LinkedList,
and the you do like:

Code: Select all

ForEach client()
  SendMsg()
Next

Posted: Sun Jan 30, 2005 7:31 pm
by DriakTravo
Thanks, I will try it out. :D Some of this networking stuff is confusing.

Posted: Sun Jan 30, 2005 7:52 pm
by olejr
Confusing and easy to get lost in.. :D
I'm a little lost myself.. :wink: (as in know some of the theory..)
And it get even better when you start to talking about lag and stuff(!)

BTW: I would use only SendNetworkData/RecieveNetworkData.. Not xxNetworkString()

Posted: Mon Jan 31, 2005 6:18 pm
by DriakTravo
so how would I write this? I dont know how to find a list of clients connected to the server.

Posted: Mon Jan 31, 2005 8:03 pm
by olejr
When NetworkServerEvent() return 1 it's a new client connecting..
Then use NetworkClientID() to get the ID of that client....