Box collision with a a vector of objects and a player

this is where the collision is handeled:

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
for (auto it = shapes.begin(); it != shapes.end(); it++)
		{
			if (player.getGlobalBounds().intersects(it->getGlobalBounds()))
			{
				if (player.getPosition().y + player.getOrigin().y >= it->getPosition().y )
				{
					player.setPosition(player.getPosition().x, it->getPosition().y - player.getOrigin().y);
					touchingBottom = true;
				}

				if (player.getPosition().x - player.getOrigin().x <= it->getPosition().x + it->getGlobalBounds().width  && 
					player.getPosition().y + player.getOrigin().y > it->getPosition().y)
				{
					player.setPosition(it->getPosition().x + it->getGlobalBounds().width + player.getOrigin().x, player.getPosition().y);
					touchingLeft = true;
				}


				break;
			}
			else
			{
				touchingBottom = false;
				touchingRight = false;
				touchingLeft = false;
			}
				
		}


it works until there is a wall on the left side. instead of not stopping it just pops up on top of the boject to the left.

is there a better way for collision in my situation?!

here is the whole program but I felt it would be a wall of text here:
http://pastebin.com/wr8R1rX1
Last edited on
bump. i'm really stuck :(
I'm not entirely sure how your program works, but are you changing the position of the object the player is colliding with? If not, could it be that it is trying to place the player in the same position as the object but can't, so it puts it on top?
sorry, i'll had comments for the collision part.

yes, that's the problem. but i'm not sure how to stop it while keeping the collision that's working now to keep working. or if anyone knew a better way to do this. because i feel this is no the best way.

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
for (auto it = shapes.begin(); it != shapes.end(); it++)
			{
				//check if the player intersects at all with the current shape
				if (player.getGlobalBounds().intersects(it->getGlobalBounds()) && it->getFillColor() != sf::Color::Red)
				{
					//check what part of the side the collsion is. this checks if it's touching the bottom
					if (player.getPosition().y + player.getOrigin().y >= it->getPosition().y)
					{
						player.setPosition(player.getPosition().x, it->getPosition().y - player.getOrigin().y);
						touchingBottom = true;
					}
					//check if it's touching the left side. not sure if this works
					if (player.getPosition().x - player.getOrigin().x <= it->getPosition().x + it->getGlobalBounds().width  &&
						player.getPosition().y + player.getOrigin().y > it->getPosition().y)
					{
						player.setPosition(it->getPosition().x + it->getGlobalBounds().width + player.getOrigin().x, player.getPosition().y);
						touchingLeft = true;
					}

					//if it's touching a shape it just breaks the loop
					//not sure if this is a smart idea but if i don't the code below turns it all off
					break;
				}
				//this isn't part of the problem at all, but it just checks if the player is touching lava
				else if (player.getGlobalBounds().intersects(it->getGlobalBounds()) && it->getFillColor() == sf::Color::Red)
				{
					paused = true;
				}
				//if none of this is true above, it just says nothing is touching anything
				else
				{
					touchingBottom = false;
					touchingRight = false;
					touchingLeft = false;
				}

			}
Last edited on
Are all of the objects and the player set relative to the same origin?

I don't think that break is necessary. Wouldn't it stop the loop from checking if the player is touching more than one object? I think you should set touchingBottom/Right/Left to false before the loop, and not have that else block. You might want a break statement in the touching lava block though.
Take a look at this example, which was directly inspired by:
http://www.metanetsoftware.com/technique/tutorialA.html

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <cmath>

class vec2f {
public :
	vec2f() { x = y = 0; };
	vec2f(float _x, float _y) { x = _x; y = _y; }

	float x, y;
};

class Entity {
public :
	Entity() { dimension = vec2f(1.0, 1.0); }

	bool isColliding(const Entity* entity, vec2f& collisionVector);

	vec2f position;
	vec2f dimension;
};

class Block : public Entity {
public :
	Block() : Entity() {}

};

class Player : public Entity {
public :
	Player() : Entity() {}

};

bool Entity::isColliding(const Entity* entity, vec2f& collisionVector) {

	//The collision vector can be used to move either of the intersecting entities.

	float xIntersect = (dimension.x + entity->dimension.x) - (fabs(dimension.x - entity->dimension.x));
	float yIntersect = (dimension.y + entity->dimension.y) - (fabs(dimension.y - entity->dimension.y));

	if (xIntersect <= 0 || yIntersect <= 0) { return false; }

	if (xIntersect <= yIntersect) {
		collisionVector.x += xIntersect * (dimension.x < entity->dimension.x ? -1.0 : 1.0);
	}
	else {
		collisionVector.y += yIntersect * (dimension.y < entity->dimension.y ? -1.0 : 1.0);
	}
	return true;
}

/*

The dimensions of the entities are set up kind of funky.
If dimension.x = 1, and dimension.y = 1, then the entity will be 2x2.

This is so, because the origin of each object is at the exact center, as opposed to one of the sides.
So really, the dimensions are half-lengths of each dimension.

The following entity has a 2x2 bounding box, because it's dimensions are 1 and 1.


<-1-><-1->
*--------*^
|	 |1
|	 |v
|	 |^
|	 |1
*--------*v

*/

int main() {

	vec2f collisionVector;

	Player* player = new Player();
	Block* block = new Block();

	/*By default, the player and the block will be colliding, because I haven't explicitly overwritten the values of the position vectors*/

	std::cout << "The player and the block are" << (player->isColliding(block, collisionVector) ? "" : "n't") << " colliding!" << std::endl;

	std::cout << "Collision Vector:\t" << "[" << collisionVector.x << ", " << collisionVector.y << "]" << std::endl;

	std::cin.get();

	delete player;
	delete block;
	return 0;
}
Last edited on
Topic archived. No new replies allowed.