Collission Detection, Response and Timing in 2D Engine

Started by
1 comment, last by Commodore 18 years ago
Hi! I'm currently working on a platform 2D Engine. What I've accomplished so far is the ability to run around with my character on the map. It's a tilebased engine and the characters is represented by simple rectangles for collission detection against the tiles (no pixel-perfect collission). I've got a Update()-method for the character which looks like this:

void CPhysObject::Update(float fDT)
{
	// Integrate
	vVelocity = vVelocity + vAcceleration*fDT;
	
	Main();	// Calls LUA-function Main for this character, allowing it to change speeds
	vVelocity = vVelocity*fDT;	// Scale the velocity vector for integration to position
	HandleWorldCollission();						
				
	// Integrate
	vPosition = vPosition + vVelocity;
	vVelocity = vVelocity/fDT;
	vNewPosition = vPosition;
}
The Main()-method calls a LUA-function "main" in the character .lua-file. The lua-file may then change velocities (for example; set the velocity.y-component to -5 if the user press space bar in order to make a jump). After the Main() has been called I have to scale the velocity with fDT, otherwise "HandleWorldCollission()" will not be able to predict the next position. The HandleWorldCollission() method starts with the characters' current position and moves in the velocity direction with small steps until it reaches (vPosition+vVelocity). In each small step collission against the world is checked and if a collission is found, the velocities are changed to "valid" values. This is working really great actually, I'm able to set the game speed by changing fDT and regardless of which fDT I have the characters will have the same jump length. I also scale fDT with the FPS in order to make the game go equally fast on all computers. Now, the problem is that I can't figure out how to implement the Character-to-character collission response code. This is my idea of how it needs to be implemented: * Find the character with the greatest velocity vector length * Make "rays" with the character velocities divided by this length * Loop from the characters start positions to the end positions using the rays. Detect any collissions and call a CollissionAccured()-function in the characters LUA-script to make the LUA-programmer decide what to do for response. This feels rather complex and also I guess I need to check collission with the world yet another time again (!) since the velocities are changed due to character-collission-response. Also, when the lua-function CollissionAccured() is called, the velocities needs to be scaled down again (or the game wouldn't go equally fast on all computers). Is this really the "right" way to do it? It just feels very very complex to move all the characters in small steps at the same time and also check collissions with the world 2 times. Thanks in advance! [edit: How do you make the source code syntax highlighted? I tried but it didn't work..]
Advertisement
Firstly you really should do:

vPosition = vPosition + vVelocity + 0.5*vAcceleration*fDT*fDT;

To maintain constant movement curves for all timesteps.

Secondly, what's with multiply and then dividing vVelocity by fDT. That kind of thing can introduce cumulative errors, and it's confusing. Better to leave it alone and do:

vPosition = vPosition + vVelocity*fDT + 0.5*vAcceleration*fDT*fDT;

Finally, your collision response depends on your collision detection method. Why are you using rays? What is the collision shape of your character? You should look up "swept 2d collisions" - if your characters are not rotating, then it's pretty easy to find precise collisions between them.

Thanks for your reply!

Yes, I'm using rectangles for the characters and the world.

I looked up "swept 2d collisions" and found this:
http://www.harveycartel.org/metanet/tutorials/tutorialA.html#section5 (section 5). The method I use is "multisampling" which is described under "swept tests" on the site.

The reason I do this is because if I'm only doing simple static collision tests every frame, the following could happen: Suppose the character is 5 pixels wide and is moving at a constant velocity of 10 pixels per frame. Also suppose there is a thin object in his way. This is what it would look like:

("O" is the character and "|" is the object)
Before
------
O|

After
-----
| O

A static collision detection approach would not detect this. Obviously I have to divide the velocity into smaller steps (=>1pixel/frame) and check the collision in every step.

For this to work, the collision detection routine needs to know the "real" velocity; that is, the exakt number of pixels the character will move in this particular moment with this particular fDT. That's why I don't use the formula for getting the position directly from velocity and acceleration (vPosition = vPosition + vVelocity*fDT + 0.5*vAcceleration*fDT*fDT;). Because first I need to get the velocity from the acceleration. Then check if this velocity is valid (call HandleCollision), and as I mentioned before this needs the velocity to be the "real" velocity used when calculating the position (hence, the multiplication with fDT).

Hope that made it clear why I've done it this way.

This topic is closed to new replies.

Advertisement