How to HANDLE collision?

Hey guys.
At the moment I’m stuck at collision handling for my 3D game. If I search for it online I only find fancy algorithms to detect if two objects intersect, but not how to handle it correctly.
My problem is that if I check the collision for let’s say the player and a wall and they do intersect it’s basically to late to prevent them from colliding. So how should I handle this the best way especially in 3D space where I have no deltas that says I’m going up or down.
Also where should I handle this stuff. I have a player class that includes the input handling for the movement, I have a Level class that holds the player and the single chunks (yes it’s some kind of minecraft game) and the Chunk class where the actual blocks are.
How does this all fit together?

I hope you have some tips for me =)

Hi

I explained how I plan to handle the collisions in my first person shooter here, look at the paragraph entitled “Improvement of collisions detection”. I hope that helps a bit.

skappler, a lot of times people handle it by the first frame they ‘intersect’ simply ‘push’ the player back outside (can be a little more difficult to know which direction to ‘push’ the player)

or perhaps another way

keep an oldX and oldY of the ‘last frame’(that they weren’t intersecting) so if they intersect, set their currentX and currentY back to their oldX and oldY coordinate, back when they weren’t intersecting.

Thank you I’ll check it out!

Thank you! Seems like a good idea. Still I’m not sure where I should do this. If I handle it in the player class I need to pass the level to it, this may cause some overhead.

I used rectangles “[rectangle].intersects([rectangle])”. If there’s an collision, I place the moving entity on the edge between them.
I am going to use polygons: http://www.java-gaming.org/index.php/topic,27895.0.html#msg251992
But that’s in production because I am switching from jafa2D to lwjgl.
best regards

Mind that, if you use what Phibedy does, you are able to get the MTV (Minimal translation vector), which says how far your entity has to be pushed to get out of the collision.

Mind that this only works when you use the SAT (Seperating Axis Theorem) algorithm.

Julien, your page there is still only talking about collision detection, not resolution.

Skappler, there isn’t a single answer. It depends on your game. You might even get away with not separating the objects if the velocity of separation after handling the collision is sufficiently high. If you can’t get away with it, there are three main options: push the two objects apart; roll back the time step; or roll back part of the time step. The latter is the most accurate for simulation purposes, but is also the most expensive.

The other problem you have to consider is where the resolution of the first collision creates a second one. You might end up having to solve multiple collisions in parallel with a constraint-based system. If you’re not scared of mathematics, check out http://isg.cs.tcd.ie/cosulliv/Pubs/GiangEgirl03.pdf

Yes I’m not interested in ways to detect if there is a collision. I’ve already dealt with this.

For the beginning I don’t want to make it too complicated, because I’m just started to learn OpenGL and need a basic system for that.
Roll back the time seems to be the thing that namrog proposed. I think it’s the easiest way.
To push the two objects apart I need to keep track of the movement vectors, right? Also I think this would be only useful for entity - entity collision as walls aren’t supposed to move :stuck_out_tongue:

I’m not scared of math as long as it’s not too hard :smiley: Your link seems to be very helpful and I will definitely safe it for later, but for the moment this seems to be a bit too much as I only try to have a basic system to handle collision so that I can move around properly. You still have a good point that one collision handling may cause another one. I’ll keep that in mind. Thank you very much!

In my collision detections, I’ve always passed the proposed movement vector into a new function, which returns a new vector (in the same direction) of the maximum movement distance the player can make before colliding with something.
Ie (pseudo code)

public void movePlayer() {
	If (left key is down) {
		playerVector += getMaxDistance(-1, 0, 0);
	}
}
public void getMaxDistance(Vector3f move) {
	//Do all calculations to find max movement, then return it.
	return maxMove;
}

This has always worked really well for me, with no troubles!

Really good idea. If I modify the system a bit by “collecting” all movement vectors (if 2 keys are pressed at the same time) this gets me also rid of the problem that I move slightly faster if I intend to move diagonal. Thank you!

I created a function called collisionDetectedSlide(). When a collision is detected, it does not roll back the players position, it just rolls back the component of the vector that caused the collision. So it the player only overlapped the object in the Z direction, then it just rolls back the Z movement. This means that players rolls off objects and slides along them if they hit the object at an angle. It works much better than just rolling back the movement, which tends to make the player stick to the wall when they hit it. Basically each time the player moves you store the previous X,Y,Z positions. Then revert one or more of them if the movement resulted in a collision.

Its as simple as this:

/**
 * Check if the player has intersected with a block and slide along a surface if you hit it at an angle
 * Makes for a better play experience than coming to a dead halt.
 * 
 * @param lastX
 * @param lastY
 * @param lastZ
 */
private void collisionDetectedSlide(float lastX, float lastY, float lastZ) {
	boolean undo=false;
	float x = player.getX();
	float y = player.getY();
	float z = player.getZ();
	float newx, newy, newz;
	
	undo=false;
	
	if (collisionDetected(x, lastY, lastZ)) {
		newx = lastX; 
		undo=true;
	} else newx=x;
	if (collisionDetected(lastX, y, lastZ)) {
		newy = lastY; 
		undo=true;
	} else newy=y;
	if (collisionDetected(lastX, lastY, z)) {
		newz = lastZ; 
		undo=true;
	} else newz=z;
			
	if (undo) player.undoMove(newx, newy, newz);
	
}