🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

RTS Fast Action network game - Help Please :)

Started by
7 comments, last by Sanced 23 years, 9 months ago
grr i just wrote the whole message and lost it, here we go again: Game is: Fast Action, Tile Based, Overhead view shoting game with a big map. Kinda quake but tilebased, or a SubSpace type. I''m useing DirectDraw, DirectInput, and sound but NOT DirectPlay i''m handling winsock TCP stream my self and i''m fine with that part. client - Server. Server keeps track of all clients, X,Y Position and Heading, etc. movement is done: forward, backwards, and u rotate. I want the game to be the most accurate posible. So that if u see a target in ur view, and u shoot, there''s very lil chance of a miss due to lag or desynch Problem = too many messages for the Server to handle (i think) What i did is: (all messages are like 15 bytes more or less) - u tell server u wanna move or rotate in H heading. - Server checks it, and moves u S(speed) distance in H direction. - Server tells u ur new position, heading. - Server tells everyone else bout ur movement. so everytime u move it communicates all that... too much i guess. if u wanna move 5 tiles west, each tile is 32x32, speed = 4(pixels)... its 32*5/4 = 40 Steps... all that communication happens 40 times for just 5 tiles which takes like 2,3 seconds. it work fine with 1 client, but when i got 2 clients it got already like really choppy/laggy... seems like a nice flood. i''d hate to have to broadcast movements every 3,4,5 steps, i''d lose accuracy and a Fast Action game without a great accuracy is pointless. Same thing with like predicting, suposeing movements, position... its all cute, but inacurate. Any ideas? the way i did it is basically how i liked it, how i think it would be the most accurate is it any good? is it a disaster cuase of ammount of communication? what am i missing/overlooked? please.. i don''t want to mess up my lil game =) thanks!
Advertisement
Hmm, sounds good to me. You should be more than alright with the amount of data you''re handling. One thing I can think of that gets alot of people who use Winsock... TCP doesn''t preserve message boundaries. I''ve seen too many times where the parsing code for the receiving socket assumes that an entire ''message'' has arived. Might want to re-check your winsock code... bandwidth shouldn''t be an issue yet unless you''re running on a 300 baud modem. =)
heya...

hmm i format all my msg''s with a terminating "|EOP\n"
and basically since all my msg''s are like.. independant..
when the server recv''s data,
i PEEK it,
if it has terminating "|EOP\n" i grab the data up to that terminating string. and process the msg.

what ever is still in the RECV buffer that i haven''t read.. will trigger again the FD_READ event, and i''l redo again as above... thats basically the cycle
if i don''t find a Terminating string in the PEEK''d data.. i just empty/flush whatever is in the Buffer (my msg''s are independant.. so i can flush ome and it won''t be a big deal)

This is a sample msg from client to server:
POS|1|90|EOP\n (13 bytes)
would be like POSition 1=moveforward, Heading = 90

then the server replies
POS|101|100|90|EOP\n (19 bytes)
meaning ur POSition is x=101, y=100, heading=90

and then tells all other players:
POX|3|101|100|90|EOP\n (21 bytes)
meaning POsition of other player ID = 3 changed to X101, Y100, H90

B = Bytes
So, every movement = 13B + 19B + (21B * Players) + whatever the header of TCP Packets carry. thats just every time 1 person moves 4 pixels.... hmmmmmmmmm

hmm sounds ok, true... say 4 players... that all would be only 116 bytes transmitted.. that should be no prob :/ (or maybe i''m seeing the big picture wrong)

4 players moving at the same time, which is normal =
116B * 4players = 464B which is still good

all the math tells me this should work fine grrrr

i''m gonna check my code see if i got some type of loops messed up or some kinda leak causeing saturation of some sort

Yet if anyone else sees some thing wrong in my picture..

please feel free to Advise =)
and Thanks Jon!



From the numbers it looks like your updating the position of your players at 15 ups. At 15 bytes per packet plus the 32 byte overhead for each UDP packet that works out to (15+32)*15 = 750 bytes/sec. So, from what you said later about how each packet is sent independently of each other, for 2 players it would work out to 750*2 = 1410 bytes/sec, less if your buffering the packets into 1 UDP packet (750 + 15*15). From the numbers it doesnt look like your saturating your bandwidth (even for a 56k modem). If your not using UDP, rather TCP_IP, its most likely the TCP_IP buffering or resending due to loss which is causing your bad performance. Its not advisible to use TCP_IP for an action game. Finding the weakness in your sychronization protocol is a tricky issue. There are so many possible links in the chain which could result in jerky movement. It could be your flooding the connection by calling to many send commands (possibly 30 / sec for 2 players at 15 ups each). You will need to buffer them if this is the case. Or possibly a weakness on your client side sychronization rountine, where it seems without a form of predicitive code, discarded or loss packets will result in the player stoping and then poping to the next good packet location. Further it''s possible that the problem might not lie in your communication protocols at all. It could be your client or server becomes to desynchornized (time wise) and packets are either discarded or ignored on that factor. The problem could lie on the client or server side. The best thing for debugging your network protocol is to not assume anything about how your networking is working. Put in explicit test code all along the sychronization routine and debug it carefully. It''s possible the performance problem is due to multiple bugs, so that make it even more difficult.

Good Luck

-ddn
hehehe
well i found 1 cause of the saturation:

i Got DirectInput Buffering keys... so like, when u press key to go Forward, its actually sending like 3,4,5,6,7,8,9 times the same MSG to the Server.

even if u just Tap the forward key.. its sending 3,4,5 times the same MSG to the server. didn''t expect DirectInput to be so sensible or fast

not too familiar with DirectInput so i''m exploreing how to handle that now

I did some testing (with this DirectInput problem i got), i set the server to count msg''s recv''d and bytes recv''d in msg''s. and in 20 seconds of constant moving of 1 client i got:
2318 msg''s sent to the server = 115 Msg''d per Second
15091 Byte Recv''d = 754 Bytes per second

hehehe
I''m testing in a LAN

hmmm Its all good... gonna revise my code and see whats up

basically i wanted to know if the way i did things was Acceptable, logical or wrong by what ya guys say it seems what i did should work so i''l dig into it

thanks Cya laters when i finish checking and testing more into this

(Damn i talk a lot)



OH, I forgot to mention, DON'T NAGLE! =)

The Nagle algo buffers small sends. To disable it, use

setsockopt(...);

with TCP_NODELAY.

You might want to do some kind of send buffering of your own to reduce the TCP overhead. One idea would be to collect all of he movements issued on the server between game loops, then send ALL of the clients positions to all clients in one message. Ideal is to send this about 15-25 times per second *less if it is not possible for them to move that often*

You might also want to switch to binary format. I'll give you an example that would cut the amount of data transfered during each client->server update to (5 bytes + overhead) and each server->client update to (5 bytes * # of players + overhead):



//HEADER INCLUDED FOR ALL MESSAGES.
//WHEN PEEKING, CHECK TO SEE THAT
//AT LEAST nLength BYTES ARE AVAILABLE

typedef struct _NET_MSG
{
unsigned char nLength;//length of message
unsigned char nType;//type of message
}NET_MSG, *PNET_MSG;


//LOCATION OF A SINGLE CHARACTER
//SELF EXPLANATORY

typedef struct _PLAYER_POSITION
{
unsigned char nId;//Player ID
unsigned char nX;//X coord
unsigned char nY;//Y coord
unsigned char nH;//Heading
}PLAYER_POSITION, *PPLAYER_POSITION;


//LOCATION OF MULTIPLE CHARACTERS
//NON-STANDARD 0-length ARRAYS ARE
//ACCEPTABLE IN VC++ AT THE END
//OF A STRUCTURE

typedef struct _PLAYER_POSITIONS
{
unsigned char nCount;
PLAYER_POSITION players[];
}PLAYER_POSITIONS, *PPLAYER_POSITIONS;


//NET MESSAGE SENT FROM CLIENT TO SERVER
//CONTAINS THAT CHARACTERS POSITION

typedef struct _NET_MSG_PLAYER_POSITION
{
NET_MSG hdr;
PLAYER_POSITION body;
}NET_MSG_PLAYER_POSITION, *PNET_MSG_PLAYER_POSITION;


//NET MESSAGE SENT FROM SERVER TO CLIENT
//CONTAINS ALL PLAYERS POSITIONS

typedef struct _NET_MSG_PLAYER_POSITIONS
{
NET_MSG_hdr;
PLAYER_POSITIONS body;
}NET_MSG_PLAYER_POSITIONS, *PNET_MSG_PLAYER_POSITIONS;



I am a HUGE fan of keeping character / world information that you will be passing over the network in a format that you can simply memcpy to a buffer and send. Cuts down on CPU cycles and really makes the code look clean. Just look out for padding. I threw this together pretty quick, I might have missed something, but hope you get the idea.

[EDIT] Glad you found out the problem. I forgot that you were sending move-requests to the server, that would change things a bit, but same idea.

Edited by - JonStelly on September 29, 2000 4:29:56 PM
Heya Jon,

i see ur point...hmm
so basically, i should be VERY serious bout the ammount of data to use for msg''s and do all i can to make it a minimum Efficiency is always good...

I''l do that...

And i''l basically re-check and restructure lotsa things looking for a better performance. i know there''s space for improvement in my code. time to tweak

But what scares me is that, the game got so chopy, laggy, with just 2 clients (lets say sloppy clients cause they aren''t tweaked yet nor notin), thing is.. kinda scares me that with just 2 clients this all got messed up

aye, Thanks for all the help/advise... BTW u deserve an MVP for all ur support along all this Forums


Glad to help Sanced, and thanks for the thanks.

What could have caused the lag etc... is the nagle algo. that I was talking about. What it does is buffer up sends until you have a complete packet or 300 milliseconds passed, at which time it flushes whatever data it has in it''s send buffer.
Just to let ya know in case ur curious of progress...

I'm redoing the way the server handles things... before it was Event driven controled by the the WSASelectevent.

Now i'm gonna do a nice pretty Loop to cycle thru all Clients and process 1 msg of each 1 at a time. like the UpdateFrame way we do grrafics in the main function Msg Loop, instead of UpdateFrame... UpdateSockets
where, Action = 2 bytes, client ID, and flags of what he did... +/-thrust, +/-heading,+/-fire

UpdateSockets() {
Action[0] = Processclientsocket(ClientN)
Action[1] & = Processclientsocket(ClientN + 1)
Action[2] & = Processclientsocket(ClientN + 2)
...
Action[N] & = Processclientsocket(ClientN + N)

And then Send the whole Action Struct to each client, and Action contains all clients, variations... all clients do their math, change x,y,headings, in their local records of players.
}

Seems to me its the Best way possible for all this. i can't see a more efficient way.

i'm also gonna use 3 Bytes to report movement from client to server as:
size of msg = 1 Byte
Msg Id = 1 B
Flags = 1 B (2 bits for thrust, 2 bits for heading, 1 bit for Fire)

sooo clients will send 3 Bytes telling server for movement
and server will reply to all Clients at the end of a cycle all the movements.

So the whole things is like for 10 clients lets say:
Clients send 3 Bytes for movement and fire
10 * 3Bytes are movements received by server = 30 Bytes
Server then replies 1 Byes Size of msg(which also means how many pairs of actions there are), 1 Byte Msg ID, and 10 * 2 =22 Bytes per client
so it sends out 22 * 10 clients = 220 Bytes

with 30 Bytes coming in and 220 Bytes Coming out for 10 players,
it everyone reported their movement and knows everybody elses's move. + Packet Headers of course

Does this sound almost Perfect? :D
or What did i miss we always miss something
What should i watch out for?


PS: Of course, the technique has ur inspiration in it




Edited by - sanced on September 30, 2000 1:14:53 PM

This topic is closed to new replies.

Advertisement