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:
Posted: Sun Jan 30, 2005 7:31 pm
by DriakTravo
Thanks, I will try it out.

Some of this networking stuff is confusing.
Posted: Sun Jan 30, 2005 7:52 pm
by olejr
Confusing and easy to get lost in..
I'm a little lost myself..

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