2d blocking volume

Hi all

I've got a blocking volume entity in a game I'm making and all I want it to do it stop the player/enemies from going through it, it doesnt need to knock them back or anything special. I made some code that just compares the entity's previous and current position and then resets it if it has crossed the boundaries

1
2
3
4
5
6
7
8
9
10
11
if ( playerPrevYMax <= yMin && playerYMax > yMin )
	player.SetY(yMin - playerHeight);

if ( playerPrevYMin >= yMax && playerYMin < yMax )
	player.SetY(yMax);

if ( playerPrevXMax <= xMin && playerXMax > xMin )
	player.SetX(xMin - playerWidth);

if ( playerPrevXMin >= xMax && playerXMin < xMax )
	player.SetX(xMax);


xMin, xMax, yMin and yMax are the boundaries of the blocking volume in the code above.

but this has problems handling collisions at the corners and blocks when it shouldn't. The problem I'm facing is that different entities will have different speeds so it is hard to determine which direction an entity has came from in order to determine whether to reset the x or y value.

Thanks.
Blocking volume?

Here's what I did:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
bool player::handle_collisions() {
	collisions tcol;
	
	bool did_handle = false;
	bool thisObjectHandle = false;
	
	for (int temp = 0; temp < collideQueue.size(); temp++) {
		thisObjectHandle = false;
		tcol = get_collision(prevPos.x,y,get_img()->get_width(),get_img()->get_height(),
							 collideQueue[temp]->get_position().x,collideQueue[temp]->get_position().y,
							 collideQueue[temp]->get_img()->get_width(),collideQueue[temp]->get_img()->get_height());
		
		if (tcol.top > 0 || tcol.bottom > 0) {
			if (prevPos.y >= collideQueue[temp]->get_prev_pos().y + collideQueue[temp]->get_img()->get_height())
				if (tcol.top > 0) {
					add_pos(0,tcol.top);
					set_vel(get_vel().x,collideQueue[temp]->get_vel().y);
					thisObjectHandle = did_handle = true;
				}
			
			if (prevPos.y + get_img()->get_height() <= collideQueue[temp]->get_prev_pos().y)
				if (tcol.bottom > 0) {
					add_pos(collideQueue[temp]->get_vel().x,-tcol.bottom);
					set_vel(get_vel().x,collideQueue[temp]->get_vel().y);
					ableToJump = true;
					jumpTimes = maxjumpable;
					thisObjectHandle = did_handle = true;
				}
			
			
			if (!thisObjectHandle) {
				if (tcol.bottom > tcol.top) {
					add_pos(collideQueue[temp]->get_vel().x,-tcol.bottom - 1);
					set_vel(get_vel().x,collideQueue[temp]->get_vel().y);
				}
				else if (tcol.top > tcol.bottom) {
					add_pos(0,tcol.top);
					set_vel(get_vel().x,collideQueue[temp]->get_vel().y);
				}
			}
		}
		
	}
	
	for (int temp = 0; temp < collideQueue.size(); temp++) {
		thisObjectHandle = false;
		tcol = get_collision(x,y,get_img()->get_width(),get_img()->get_height(),
							 collideQueue[temp]->get_position().x,collideQueue[temp]->get_position().y,
							 collideQueue[temp]->get_img()->get_width(),collideQueue[temp]->get_img()->get_height());
		
		
		if (prevPos.x + get_img()->get_width() <= collideQueue[temp]->get_prev_pos().x)
			if (tcol.left > 0) {
				add_pos(-tcol.left,0);
				set_vel(collideQueue[temp]->get_vel().x,get_vel().y);
				thisObjectHandle = did_handle = true;
			}
		if (prevPos.x >= collideQueue[temp]->get_prev_pos().x + collideQueue[temp]->get_img()->get_width())
			if (tcol.right > 0) {
				add_pos(tcol.right,0);
				set_vel(collideQueue[temp]->get_vel().x,get_vel().y);
				thisObjectHandle = did_handle = true;
			}
	}
	
	
	return did_handle;
}


Where the collision functions are is :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
bool collide(float x1, float y1, float sx1, float sy1, float x2, float y2,float sx2,float sy2) {
	
	if (x1 >= x2 + sx2) //left of first right of second
		return false;
	if (x2 >= x1 + sx1) // left of second right of first
		return false;
	if (y1 >= y2 + sy2) // top of first below second
		return false;
	if (y2 >= y1 + sy1) // top of second below first
		return false;
	
	return true; // must be colliding =)
	
}

collisions get_collision(float x1, float y1, float sx1, float sy1, float x2, float y2,float sx2,float sy2) {
	collisions tcol;
	tcol.bottom = tcol.top = tcol.right = tcol.left = 0;
	
	if (x1 >= x2 + sx2) //left of first right of second
		return tcol;
	if (x2 >= x1 + sx1) // left of second right of first
		return tcol;
	if (y1 >= y2 + sy2) // top of first below second
		return tcol;
	if (y2 >= y1 + sy1) // top of second below first
		return tcol;
	
	
	tcol.bottom =(y1+sy1)-y2;
	tcol.top    =(y2+sy2)-y1;
	
	
	tcol.right  =(x2+sx2)-x1;
	tcol.left   =(x1+sx1)-x2;
	return tcol;
}

collisions get_collision(obj* first, obj* second) {
	return get_collision(first->get_position().x,first->get_position().y,
						 first->get_img()->get_width(),first->get_img()->get_height(),
						 second->get_position().x,second->get_position().y,
						 second->get_img()->get_width(),second->get_img()->get_height());
	
}

bool collide(obj first, obj second) {
	return collide(first.get_position().x,first.get_position().y,
				   first.get_img()->get_width(),first.get_img()->get_height(),
				   second.get_position().x,second.get_position().y,
				   second.get_img()->get_width(),second.get_img()->get_height());
}

bool collide(obj* first, obj* second) {
	return collide(first->get_position().x,first->get_position().y,
				   first->get_img()->get_width(),first->get_img()->get_height(),
				   second->get_position().x,second->get_position().y,
				   second->get_img()->get_width(),second->get_img()->get_height());
}


And the collision struct has four float members: top, right, left, and bottom


(I'm definitely still going to make this article)
Topic archived. No new replies allowed.