Player Movement - Input + Network Messages

Started by
16 comments, last by Chumble 10 years, 7 months ago


Is your player, and all other animate objects in the game only going to move at one speed? Will you not have a speed buff, or a slow debuff for the players?

No, but I figured I'd just have the server keep track of that. If the player gets some kind of speed buff, the server will know.. it will adjust the speed server-side so when the player requests to move, it uses the current server-side speed.

As this game is really just my own little training project, I realize it will never be flooded with people, much less flooded with people who feel the need to cheat, but I'm trying to incorporate some "best practices" so that when I do work on something legitimate, I'm used to doing it right.


your server should still send a full game state every "so often" (how often can be determine based on how frenetic your game will be, how many players there are, how much traffic there already will be, etc.).

That's gonna be a tough one. I can't imagine more than 10 or so objects will be moving on a player's screen at a time. I've already tried to limit how much traffic is sent to the players by only updating their surroundings rather than the entire game, but it needs more work. I guess this will be a trial + error effort.


This also means you should have time-stamped messages, so clients know, at "this point in time" player X was at Y location, moving at this Z velocity, so you can make sure the player is at the correct state at your clients time.

That.. is interesting. I'm having a little bit of a tough time wrapping my head around that. Why wouldn't I just use NOW as my time? As long as the server is sending the most recent information and the clients are updating with the most recent information, why do I need to check times? I'm not trying to contest you, I just don't understand it. Could you possibly give an example?

Thanks,

Jeremy

Advertisement


That.. is interesting. I'm having a little bit of a tough time wrapping my head around that. Why wouldn't I just use NOW as my time? As long as the server is sending the most recent information and the clients are updating with the most recent information, why do I need to check times? I'm not trying to contest you, I just don't understand it. Could you possibly give an example?

What happens if the message takes 400 mS to get from the server to the client(it will happen, and it will take longer sometimes because of latency and packet retries), and a player has changed velocity/direction. When the client gets the message, it will place the player at the given location, and given velocity/direction, but it will be 400 mS behind where the actual player is.

If you don't simulate him moving velocity*.4 distance immediately, then you'll be seeing him behind, and when you shoot at the player, it'll be behind where he actually is, causing issues with when U believe you've hit, him, but the server sees the bullet go behind him.

That's the idea behind having everything synced for a certain time. There is no such thing as NOW when you're talking about latency and possible packet loss/retries.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Maybe I'm being a bit dense about this, but my point about NOW is that the server has the final say as to who is where. The best the server can do is try to relay this information as accurately as possible.

Yes, players will lag, and their position will be slightly off at times.. seems the best I can do is have the server update them at regular intervals to make sure they're on track.

You obviously know what you're talking about and again, I'm not trying to simply contest you. I accept that I am wrong, but in order to come to the correct understanding, I need to relay my thoughts.

I'm going to set up an example. There are two players, both are standing still.

--------------------

T=0

Player 1 starts moving right. Begins moving immediately client-side *(1)

T=1

Server receives the "Player Move Right" message. Broadcasts to all clients that Player 1 is moving right.

Player 2 still sees player 1 at the original location. Shoots at player 1 (Sends "Shoot" message to server).

T=2

Player 1 and player 2 get server's "Player 1 is moving right" message. Both player's screens are updated appropriately (Player 1's screen is adjusted, if needed).

Server gets the "Shoot" message from Player 2. Calculates that player 2 missed player 1.

Server sends the .. animate bullet message?.. to all clients to draw the bullet..?

T=3

Player 2 watches the bullet miss and cries in frustration

--------------------

*(1) - Using as accurate of prediction as I can come up with.

This seems like a very possible but understandable situation. This is a networked game and networks have lag. I don't see how adding a timestamp to each message helps. ...... unless you're saying that the CLIENT sends a timestamp to the server as well?

I don't think it would help the situation above because that is really an extreme situation, but if it was a situation where Player 2 fires at player 1 at T=1 (and sent this message to the server), even if the server didn't get the message until T=3, the server would remember that player 1 was at the fired upon position at T=1 and generate a "hit" anyways? The more I type this the more I think I still have this wrong.

:-/

I think his point was more at using dead reckoning in your code to where the client will draw other players based on where it "assumes" their position is, and by timestamping messages from the server you can read them and go "Hrm this player should be here at this point and moving this direction, well if I compare that to his current position then I know he should have been at that spot 400 ms ago, now I can guess where he should be at this second and draw him there. This point relies on the idea that the client still assumes it know what is best and just modifies that based on concrete information received from the server.

To be honest I haven't done much realtime gameplay with networking so I'm not entirely sure what the most common design patterns are for guessing movement in different games, but. Usually with games the client will assume that it is correct and in control and just relay its movements to the server, which checks them for validity and relays that information to other clients.

It's really a bit of a guessing game and this network logic changes quite a bit depending on the type of game, for instance an mmo assumes far less precision of location than does an FPS or something where getting a shot off at the right moment is the difference between terrible and good gameplay.

I'm sure we've all played a shooter that was coded horridly to where you were expected to shoot miles ahead of or behind players because their updating was so awfully designed. Gunz is a good example.


this player should be here at this point and moving this direction, well if I compare that to his current position then I know he should have been at that spot 400 ms ago, now I can guess where he should be at this second and draw him there.

o.o

.. seems much more complex than what I need. I don't plan on doing anything with projectiles and shooting bullets, etc. I think.. this is one optimization I will hold off on for now because I'm either going to go crazy trying to understand it or code it. I think I should be mostly OK without it.

I realize you are trying to make a fun multiplayer game, and I suggest you don't worry about these inconsistnecies I'm describing then. You can do what you were planning, and you'll probably have a fun game, with some noticeable inconsistencies, but as a 1st networking game, I bet it will be fun.

You can find information on the internet about client-side prediction and dead-reckoning if you want to try and improve accuracy of the objects in the multiplayer game to better understand what I'm trying to describe.

Good luck!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Ok - I have added the above features to varying success.

When a player presses a directional arrow key

1) Check to see that the corresponding "keyDown" flag is not set.

2) Set the "keyDown" flag for that direction

3) If there is a "keyDown" flag already set for an opposite direction, clear it.

When a player releases a directional arrow key

1) Check to see that the corresponding "keyDown" flag is set.

2) Clear the "keyDown" flag for that direction

After either of the above occur, I "compile" the direction to a single int. 0 = no direction, 1 = Up, 2 = Up/Right (etc, clockwise until 8=Up/Left).

I create a new network packet with this int and send it to the server. The server gets this message and updates a new field on the player object called moveDirection.

There is a new thread running on the server called UpdateThread.

1) Loop through all entities. If the entity has a "moveDirection" > 0, update their position server-side.

2) For each entity, if it is found that their moveDirection had changed since the last loop, broadcast this new moveDirection to all clients.

3) Increment a counter. If the counter is > 100, reset the counter and broadcast the actual entity coordinates to all clients (to ensure they are synced).

4) Sleep for 10ms

The client's main update loop performs a very similar process to the server's UpdateThread

1) Loop through all entities. If the entity has a "moveDirection" > 1, update their position client-side.

2) "Sleep" for 10ms (since it's not in a thread I needed to make my own sleep function .. just uses a while loop to pause execution for X ms)

So.. the result..

When connecting to my own server using 127.0.0.1, it seemed moderately OK. A little twitchy as the server corrected my position.. slightly more than I would have guessed but tolerable I suppose.

When connecting a second client to the server, suddenly performance was cut in half. I cannot imagine why as the loop running through two entities instead of just one should still only take a minuscule amount of time. But the end result was the players seemed to move at about 50% normal speed.

Speed was decreased by another 50% with a third client.

Also, when connecting to myself using my external IP address, performance right off the bat (even with a single client) was very sloppy. I could move in a direction but I was jumping around almost constantly.

The more I type, the more I think something has to be wrong client-side. If the client is just getting a message that "Player 1 is moving left", there should be no reason why that player would move slower between the server synchronization updates that only happen once a second.

Anyways, if anyone has any further thoughts, feel free to post them. If not, I will continue plugging away at this to see if I can improve it. I'm hoping I haven't already hit the limits of TCP.

I have uploaded a video of this. In this video, I connect to the server, can run around... generally fine. Still not perfect.

Then I connect several simulated clients that just move in circles. As you can see, for each client connected, the performance just gets completely shot.

Edit: I'm an idiot. Had an extra sleep inside the loop on the client side. No idea why it was there. Got rid of it and I'm good.

This topic is closed to new replies.

Advertisement