Speeding up Sockets
BlitzMax Forums/BlitzMax Programming/Speeding up Sockets
| ||
So I'm working an a massively multiplayer online game client, and I'm running into a little snag. Right now (in the early stages), every time a player moves, the new coordinates are sent to every user in the game. The game runs VERY slow with two players, and I was wondering if you could give me any pointers on how to optimize my code. I've included a link to an archive with my code. You need python to run the server. To get the game running, cd into the server directory and type "python simpleserver.py". Then launch client and client copy to test it out with 2 users online. You control using arrow keys. http://www.gamemakersgarage.com/downloads/vulcan.zip You want to compile client.bmx if you're going to compile. network.bmx controls networking, and player.bmx controls player functions. Thank you very much in advance for your help, and feel free to use the code you see in your games. foosh |
| ||
Hi foosh! I took a look at your code. There are several things you should probably change or at least reconsider: - Do not send messages updating coordinates every time they change, send them a couple of times a second instead... a quick change on you main loop in order to send /receive positions only 5 times a second keeps your famerate higher. Local elapsed:Int=MilliSecs() While Not KeyDown(Key_ESCAPE) Or AppTerminate() Cls time_passed_secs = stop-start time_passed_secs = time_passed_secs/1000 start = MilliSecs() DrawText "fps: " + (time_passed_secs*1000),200,465 main_player.UpdateState() For Local o:TGameObject=EachIn GameObjectList o.DrawSelf() Next DrawText "alias: " + player_name,0,465 DrawText "x,y: " + main_player.X+","+main_player.Y,400,465 Flip stop = MilliSecs() If(elapsed+200<MilliSecs()) If Not (main_player.X=main_player.pX And main_player.Y=main_player.pY) Then game_network.sendCoords(main_player.X,main_player.Y) game_network.updateMap() elapsed=MilliSecs() End If Wend - While receiving data from the network you are getting loads of intermediate positions from the remote objects... and you are probably only interested in the "latest one" and can easily calculate the intermediate points to make remote objects move smoother on the local display. Some sample code to ilustrate it (it probably breaks the function purpose but try it out to see what I mean): Also, going thru the objects list several times, for each and every single one of those intermediate changes, was killing your your framerate. You would probably do much better if you got a notification from the game server on "when" and "what" objects changed, so you would request the latest (not the history) info on the ones that "interest" you. Method updateMap() Local other_player:TOtherPlayer Local mapState:String Local parseCoords:String[] Local x,y,id:Int Local name:String Local last:Int[][] Local unfinished:Int=1 Local updated:Int=0 While(unfinished=1) If SocketReadAvail(socket) > 0 Then mapState = ReadLine(stream) If mapState Then parseCoords = mapState.split(":") id = parseCoords[0].toint() parseCoords = parseCoords[1].split(",") x = Trim(parseCoords[0]).toint() y = Trim(parseCoords[1]).toint() name = Trim(parseCoords[2]) Print x+"*"+y+"*"+name+"*"+id+"*" updated =+ 1 End If Else If(updated) For Local o:TGameObject=EachIn GameObjectList If o.ID = id Then o.X = x o.Y = y Else other_player = TOtherPlayer.Create(name,file_server+"playerorange.png",x,y,id) End If Next End If unfinished=0 End If Wend End Method - A echo server may be used for game room handling... but it is NOT your best option for keeping track of remote objects in real time... use must use UDP for that. PLS PS: "I'm working an a massively multiplayer online game client"... you will fail (sorry!). Code a few smaller networks games (real time or turn based), have fun, and give yourself a chance of finishing a game. |
| ||
I know I may not finish, but regardless I wanna get as far as I can, and then perhaps use what I have to make a fun game. It's been a great learning experience so far, and I'm enjoying it! I was considering porting my code to C++ for threading capabilities, etc... but the overhead is just too much, so I just wanna push the limits of BlitzMax. Thank you very much for your help! I'll be implementing your suggestions, and I also think I found a few ways to optimize my own code since I last posted. I'll post occasionally about progress. (it'll be slow) =) Thanks a lot! foosh |
| ||
The main problem for the slowdown is the fact that you trash the socket totally. WriteLine / ReadLine are a TOTAL no go for realtime! They work by reading byte per byte till they find an end line, which is about the worst thing you can do! Make your application write packets. A packets contains: 1. Unique ID definining the content 1.2. Size of the packet in whole if it has varying sizes (for something that transfers strings like chat for example) 2. The content as specifyed by the Unique ID For example for the position update you would have a const P_UpdatePosition:int = 1 and the packet structure would be byte | float | float | float | float | float | float or in non typed: P_UpdatePosition | X | Y | Z | RotationX | RotationY | RotationZ the | are not written into the package, they are only to visually seperate the different byte parts. That way the server / client just has to: 1. Check if bytes are available 2. if yes, read the first byte to get the type of package 3. Wait till as many bytes are at least available as the message size is. In above case this would mean wait till at least 24 bytes are available 4. ReadBytes and read the whole remaining message as 1 memory block. 5. parse the data out of the block in the way you prefer (TBank, memcopy into a TPositionUpdate type instance, ...) If your game is ground based with no free 3D movement, RotationX and RotationZ can be removed theoretically. if it is 2D you can remove the Z as well |