tweaking movement and collision in 2D RPG

Started by
5 comments, last by hplus0603 19 years, 2 months ago
hi, im working on a 2D, actiony online RPG. my goal is to be able to handle 30 players on a dedicated server running on a cable connection. anyway, i have been thinking more about my movement and collision detection system and how i could tweak the former to adapt better to lag. also, my collision detection is kind of hacked. first, let me explain how the movement works. the game has an overhead view like a traditional old school console RPG, ala Final Fantasy 3. i use the mouse for movement. when you click on the screen, your character then walks in a strait line to where you clicked. if he collides with another person or a wall he stops. using this kind of movement, its easy to sync and keep secure. anyway, currently it works like this. -client clicks somewhere and sends to the server "im standing at X,Y and i clicked on X2,Y2, at time T". the client then calculates the strait path and sets his velocity, and starts immediately moving to his destination. -the server receives this, verifies its legal, calculates a strait path, using the timestamp, sets velocity, and does a "jump" to make up for lost time. the server then forwards this packet to the server and the clients do the same. ok, there is just one problem. i notice that if theres a high ping, a player will appear to "hop" around because of the "jump" i do to make up for lost time. i know one method is to instead of jump just have the character appear to quickly speed up to the end of the jump. but, i would like to do more then this. i was thinking that instead of the player immediately moving when he clicked, he would send to the server "im at X,Y and clicked at X2,Y2 at time T"..the server then verifies and immediately starts moving the player on his simulation. he then sends to all clients in the area about the movement including the sender of the packet and then the clients play "catch up" with the server (instead of the server and the clients playing "catch up" with the client who moved). this way, the "jump" should be dependant on yoru connection to the server only and the jump wouldnt be as big. the downside is that the player will no longer have immediate action with his movements. however, i dont think it will be that bad (if you ever played UO, i believe they do this same thing). also, another downside is the fact it uses more bandwith this way, since the server will have to tell a client who wants to move "ok, you can move now". i was thinking another benefit is that i can also scale the bandwith usage on the server. i could do this by not immediately reacting to movement requests, so that when it was laggy, it would be slower to move. i do believe RakNet actually handles all queue'ing and packet splitting for me though. however, if i let RakNet do it, i think this will slow down everything, which may or may not be better then just having movement slowed down, im not sure.. also, about collision detection. currently i dont send any corrections to clients about collision detection. it is all done by simple 2d AABB's. the client and server both do collision detection, and there are no corrections sent. it was hard to get this to work perfectly, but if i send floats over the wire, and also use my hacked collision detection scheme, it seems to be 100% accurate on all machines. this is only based on tests ive done by myself though, with low ping obviously (i can set a "sleep time" for raknet so it doesnt do anything for X MS therefore giving me a higher ping). anyway, i really dont like my collision detection scheme. it seems kind of hacked, and its inneficent. i actually have to cap the frame-rate for my game too if i use this method. basically how it works is, you take tiny steps towarsd your destination instead of just moving to your destination. this might add up to a lot of checks on the server, especially considering i dont do any space partitioning. i also dont like capping the frame rate since everything just doesnt run as smooth. now, if i just use regular collision detection and send unsigned shorts for positions over the wire, it seems to still be very accurate. in fact the only time it will go out of sync is if i stand on the edge of a collision and click rapidly trying to "get out of it". however, when the client sends "this is where i am", the server verifies, and if its not legit, he sends the client where he should be. the client then gets set to this position. so, under these coditions, you might appear to "rubber band". sorry for such a long post, i didnt want to make 2 seperate threads though [grin]. im not sure what i should do on either of these situations. any advice is appreciated. [Edited by - graveyard filla on January 16, 2005 5:22:19 AM]
FTA, my 2D futuristic action MMORPG
Advertisement
One option is to make it so that player avatars never collide with each other. That way, you won't have the big troll blocking the tunnel so nobody else can get by. Then you only need to collision test against static stuff, and possibly mobs, which all are much more predictable.

Another option is to run physics at a fixed rate (say, 20 steps per second?) but run rendering as fast as you can, using interpolation for position/orientation of objects you render. That way, you could get the "capping the frame rate" that you want, without having to slow down the visible frame rate.
enum Bool { True, False, FileNotFound };
hi hplus,

so you think its worth it to do the inneficent collision detection, to prevent these errors? also the bigger issue - sending floats over the wire instead of unsigned shorts. to be 100% accurate i must send floats.

also, do you think i should not have the client respond immediately to input? like i said, with high pings, the 'jump' is very noticable. if i had the client wait for a resonpse from the server, this should cut that jump in half at the expense of a slower reaction time and bandwith. with a decent ping though (~100), it looks flawless.

actually, after thinking about it more, this might actually be a bad idea. because then, the client who wants to move must "jump" to make up for lost time.. so, the clients own movement will appear jumpy during high ping.. not sure how well that will work out..

thanks for any more help.

[Edited by - graveyard filla on January 16, 2005 7:01:46 PM]
FTA, my 2D futuristic action MMORPG
You don't need to send floats. The trick is that you only ever send "I want to move here" updates. When the user clicks on the screen, you should truncate that to short precision before your program deals with it (even if you convert back to floats to do math). That way, it will be the same on all machines, including the client.

Regarding inefficient collision detection: Yes, I think you should do it server-side. Once the profiler tells you it's too inefficient, you could re-code it using a quad tree, or the sweep-and-prune algorithm. But one thing at a time, and no thing before its time.
enum Bool { True, False, FileNotFound };
so your saying, when a user clicks, i truncate his position to the next possible short integer value? wow, im surprised i didnt think of that =). so when i move, i might appear to slightly jump half of a pixel.. however, i dont think this is very noticable anyway..

im still not sure what to do about the movement system though. im gunna have to test it more with people to see how jumpy it truly is.

thanks again.
FTA, my 2D futuristic action MMORPG
oh, and i forgot..

could you please show me what you mean by the "fixed rate" thing? i had tried something like this, but it didnt work out well. basically, i tried doing it like this:

while(game running){   //only update the movement and other logic at best 100 FPS  if(GetTime() - last_time_updated > 10)  {     Update_Characters_And_Stuff();     last_time_updated = GetTime();  }  Update_Network();  Render();}


this didnt work out too well though.. i think im doing something obviously wrong.
FTA, my 2D futuristic action MMORPG
One problem might be that if your time elapsed is 20 milliseconds, you won't update characters twice. I'm assuming "updating characters" means actually calculating physics.

Note that, when you render, you should render at a specific point in time. You then render entities at a position which is extrapolated from their last two actually calculated positions. This means that "update characters" turns into "copy current state into saved state; then update current state".
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement