collision problem in online game (2D)

Started by
23 comments, last by graveyard filla 19 years, 4 months ago
hi, im working on a multiplayer action / RPG, 2D using square tiles. i use the mouse for movement in the game to help save on bandwith and make it easier to sync. anyway, when a player clicks, his character walks in a strait line to where the user clicked untill he either hits a wall / another character / clicks somewhere else. when he clicks, he sends the server where he clicked and a timestamp. when the server gets this, he does the same calculation for the strait line, finds out how much time has passed with the timestamp, and then i make up for lost time by moving to pos + (velocity * time_passed) (essentially he "jumps" to make up for lost time, so that everyone is on the same spot on all clients and the server). he sends the packet to all clients in his area and they do the same. this puts the characters in the same spot on all clients and the server. i also use the same system for guns / projectiles. anyway, heres the problem. when i do that initial "jump", i don't know how to make sure that the jump wont send me through a wall or another character or anything. i know this is probably easy but im just mathmatically retarded. thanks a lot for any help. [Edited by - graveyard filla on December 6, 2004 1:32:01 AM]
FTA, my 2D futuristic action MMORPG
Advertisement
It would seem much simpler for all players to send their data - like their position and current state - to the server, and for the server to appropriately send data to all players in a given area. This would save on bandwidth.

And having your player calculate their movements packet by packet and then sending a packet whenever their state changes would be much simpler. It would also allow you to check for collisions on the client end.

However, with your method, the best way to do it is check and see if the tile being clicked on is movable or not. ditto for the first tile in the movement series.
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
Quote:Original post by andrewk3652
It would seem much simpler for all players to send their data - like their position and current state - to the server, and for the server to appropriately send data to all players in a given area. This would save on bandwidth.

And having your player calculate their movements packet by packet and then sending a packet whenever their state changes would be much simpler. It would also allow you to check for collisions on the client end.


sorry, i think your misunderstanding me. the player sends the server where he clicked when he clicks to move. the server updates his simulation and then relays the packet to all other clients in his area and they do the same. i don't see it using any less bandwith then this... sorry if im misunderstanding you.

Quote:
However, with your method, the best way to do it is check and see if the tile being clicked on is movable or not. ditto for the first tile in the movement series.


im sorry but i don't follow. why would the tile being clicked on be effected? the initial "jump" i make should usually only effect maybe the tile im standing on or if the lag is bad a tile adjacent to the tile im standing on. i think i have to draw a line from where i currently am to where the end of the "jump" is, and if the line goes through something solid, i move to the edge of that object. i'm just not sure how to draw this line and find what it intersects with at what positions.
FTA, my 2D futuristic action MMORPG
Firstly if you plan on having many people play your game don't follow andrewk3652 as that way makes it immensly easy to cheat - always have the client just request things which the server then actually carries out!

As for making sure characteres dont' jump walls etc there are a number of ways. The easiest though is probably just to do multiple checks. If 1 second has passed and your maximum time step is 100ms, then move your character as if it 100ms had passed and re-check. Do that 10 times and it'll be the same as executing one big step of 1 second except that you can be sure you haven't jumped over anything. You can also do more advanced things like useing swept bounding boxes but multiple checks is easy to impliment (just put a loop round your current check to split it up) and its simple to debug. If speed becomes a problem look into something better but it'll probably work fine.
a few thoughts:

1) code time and velocity into your collision detection. That's doable but probably not what you want. If all you use it bounding boxes though, it really would be rather simple. (notice i said "rather" :-)

2) don't jump. Instead of factoring in the time delta, you simply ignore it. You will notice this as a delay in the actions of the character which is probably not what you want, but it would work.

3) try preemptive movement on the client with server corrections. That is, if client presses UP, move the player on the screen up immediately (for instant reaction) and also notify the server of the UP movement. The server then sends back it's "check". If the server and client don't match at that point, you can "snap" the client character back to where he should be. You'll have somewhat jerky movement, but instant reaction from input.

Quote:Original post by kaysik
As for making sure characteres dont' jump walls etc there are a number of ways. The easiest though is probably just to do multiple checks. If 1 second has passed and your maximum time step is 100ms, then move your character as if it 100ms had passed and re-check. Do that 10 times and it'll be the same as executing one big step of 1 second except that you can be sure you haven't jumped over anything. You can also do more advanced things like useing swept bounding boxes but multiple checks is easy to impliment (just put a loop round your current check to split it up) and its simple to debug. If speed becomes a problem look into something better but it'll probably work fine.


what do you mean by maximum timestep here? also how do i decide which is a good value for it? i need it to be as precise and consistant as possible.

Quote:Original post by leiavoia
a few thoughts:

1) code time and velocity into your collision detection. That's doable but probably not what you want. If all you use it bounding boxes though, it really would be rather simple. (notice i said "rather" :-)


could you explain what you mean here? and yes, im just using bounding boxes and square tiles for collision.

Quote:
2) don't jump. Instead of factoring in the time delta, you simply ignore it. You will notice this as a delay in the actions of the character which is probably not what you want, but it would work.


well, that won't work too well. the game is action-y and theres real time projectiles flying through the air - i need it to be as synced as possible to reduce errors as well as possible.

Quote:
3) try preemptive movement on the client with server corrections. That is, if client presses UP, move the player on the screen up immediately (for instant reaction) and also notify the server of the UP movement. The server then sends back it's "check". If the server and client don't match at that point, you can "snap" the client character back to where he should be. You'll have somewhat jerky movement, but instant reaction from input.


im a little confused here. there is already immediate reaction. let me try to explain better how movement is done:

-the player clicks somewhere on his screen. (theres no arrow key movement) now on his machine his character starts walking to where he clicked, moving in a strait path. he will continue moving untill he collides with a wall, a person, or clicks to move somewhere else.

-when the player clicks, he sends to the server "this is where i clicked at time T". the server calculates velocity just like the client did and then he "jumps" that client on his simulation (vel*dt) pixels, as to make up for latency.

-the server now sends this message to all the clients in the area of the client whos moving. these clients do the same thing the server did - set the position and velocity of the client who moved.

using the mouse for movement makes it pretty easy to sync movement and its also very low bandwith. i just need to figure out how to detect collisions in between where i am and where i will be after i make the "jump".

thanks again for anymore help.
FTA, my 2D futuristic action MMORPG
then go with option #1 - start researching the Separation of Axis algorithm. What that does is compare two polygons (boxes in your case) for collision and also reponse, but you can throw in time and velocity as well for perfect collisions. Check out oliii's code and tutorials called "polycoly". It's what i'm using for my project currently.
Quote:Original post by graveyard filla
Quote:Original post by kaysik
As for making sure characteres dont' jump walls etc there are a number of ways. The easiest though is probably just to do multiple checks. If 1 second has passed and your maximum time step is 100ms, then move your character as if it 100ms had passed and re-check. Do that 10 times and it'll be the same as executing one big step of 1 second except that you can be sure you haven't jumped over anything. You can also do more advanced things like useing swept bounding boxes but multiple checks is easy to impliment (just put a loop round your current check to split it up) and its simple to debug. If speed becomes a problem look into something better but it'll probably work fine.


what do you mean by maximum timestep here? also how do i decide which is a good value for it? i need it to be as precise and consistant as possible.


Most games have a maximum upper frame length (typically rendering up to 60 frames per second or something like that). In the provided example, if each of your frames was a tenth of a second (i.e frames per second = 10) and you received a message with a delay of 1 second, you would want to simulate the "missing" frames when you're accounting for that delay. Since you're missisng ten frames, you'd simulate ten frames in turn. No jumps involved.

As for choosing a frame length, whatever looks smooth. 10 is too small in most cases. If you make each frame too short (lots of frames per second) then you'll be doing a lot of needless work, since the player won't be able to notice anyway. I think animated movies run at 24 frames per second.
Jetblade: an open-source 2D platforming game in the style of Metroid and Castlevania, with procedurally-generated levels
so essentially, i would do this?

when i get a "client clicked over here to move" packet, i extract the data from the packet and call this function:
void Player::Process_Movement(float dest_x, float dest_y, Uint32 timestamp){       //set our new destination coordinate	current_dest_x = dest_x;	current_dest_y = dest_y;       //calculate velocity	xVel = current_dest_x - (xPos+(width/2));	yVel = current_dest_y - (yPos+(height/2));	float diff = sqrt((float)yVel*yVel + xVel*xVel);	float invlen = 1.0f/diff;	xVel *= (invlen*200);	yVel *= (invlen*200);	//how much time has passed since the user actually clicked to do this action?	Uint32 dt = RakNetGetTime() - timestamp;	        //we will do steps in 10 millisecond increments        Uint32 timestep = 10;        //while we haven't done a time step as big as our DT        while(timestep < dt)        {            //how many seconds have passed since this timestep?	    float secs_passed = (float)timestep * 0.001f;	                //move our character this far            xPos += (xVel * secs_passed);	    yPos += (yVel * secs_passed);                       //if we are colliding with anything in this spot, we can stop testing for collisions 	   if(Collision_Detection_And_Reaction_With_The_Map_And_Other_Characters())    		 break;             //advance another 10 MS           timestep+=10;         }}


so, how does that look? most notably the end of it, where i try to do the timestep thing, is where i'm not sure i did it right or not.

thanks again everyone.

[Edited by - graveyard filla on December 6, 2004 3:18:48 PM]
FTA, my 2D futuristic action MMORPG
Er...ms_passed is an undefined variable. Other than that, your use of "timestep" as an incremented variable feels weird; a name like "makeup_time" or something might be more appropriate. Make certain that your update of xPos and yPos is correct (since I don't know what ms_passed is, it's hard to say). But that looks reasonable.
Jetblade: an open-source 2D platforming game in the style of Metroid and Castlevania, with procedurally-generated levels

This topic is closed to new replies.

Advertisement