Collision Detection Only affects last element

The collision detection that I have implemented only affects the last element of the vector container, and nothing else. Here is a sample program of what I am talking about.

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
92
93
94
95
96

bool BoundingBox(Rect & Object1, vector<Rect> & Object2);


int main()
{
	sf::RenderWindow Window(sf::VideoMode(800, 600), " Vector Collision Test ");

	
	Rect player(sf::Color::Red);
	player.setPosition(300.0f, 390.0f);
	

	Rect box;

	vector<Rect> Boxes;
	
	Boxes.push_back(box);
	Boxes.push_back(box);
	Boxes.push_back(box);
	Boxes.push_back(box);


	int k = 1;

	for(int i = 0; i < Boxes.size(); i++)
	{
		Boxes[i].setPosition(k * 100.0f, 100.0f);	
		k += 1;
	}

	float Speed = 0.5;
	bool Collision = false;

	int counter = 0;
	while(Window.isOpen())
	{
		Window.clear();




		sf::Event Event;
		while(Window.pollEvent(Event))
		{
			switch(Event.type)
			{
			case sf::Event::Closed:
				Window.close();
				break;

			case sf::Event::KeyPressed:
				if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
					Window.close();
				break;

			}
	
		}

		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
			player.move(-Speed, 0.0f);
		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
			player.move(Speed, 0.0f);
		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
			player.move(0.0f, -Speed);
		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
			player.move(0.0f, Speed);
	
	

		Collision = BoundingBox(player, Boxes);

		if(Collision)
		{
			counter++;
			cout << "Box Has Been Hit: " << Collision << endl;

		}
		else if(!Collision)
		{
			cout << "Box Has Not Been Hit: " << Collision << endl;
		
		}

		for(vector<Rect>::iterator itr = Boxes.begin(); itr != Boxes.end(); itr++)
			Window.draw(*itr);



		Window.draw(player);
		Window.display();
	}

	return 0;
}



class for collision detection or Bounding Box
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

	OrientedBoundingBox(const Rect & rect)
	{
		sf::Transform tran = rect.getTransform();
		Points[0] = tran.transformPoint(0.0f, 0.0f);
		Points[1] = tran.transformPoint(rect.getSize().x, 0.0f);
		Points[2] = tran.transformPoint(rect.getSize().x, rect.getSize().y);
		Points[3] = tran.transformPoint(0.0f, rect.getSize().y);

	}

	OrientedBoundingBox(vector<Rect> & rect)
	{
		for(int i = 0; i < rect.size(); i++)
		{
			sf::Transform tran = rect[i].getTransform();

			Points[0] = tran.transformPoint(0.0f, 0.0f);
			Points[1] = tran.transformPoint(rect[i].getSize().x, 0.0f);
			Points[2] = tran.transformPoint(rect[i].getSize().x, rect[i].getSize().y);
			Points[3] = tran.transformPoint(0.0f, rect[i].getSize().y);
		
		}
	
	}


sf::Points[4];

	void ProjectOntoAxis(const sf::Vector2f & Axis, float & Min, float & Max)
	{
		Min = (Points[0].x * Axis.x + Points[0].y * Axis.y );
		Max = Min;

		for(int j = 1; j < 4; j++)
		{
			float Projection = (Points[j].x * Axis.x + Points[j].y * Axis.y);
		
			if(Projection < Min)
				Min = Projection;
			if(Projection > Max)
				Max = Projection;

		}


The collision detection that I am using is the separating axis theorem. What would cause the last element only to be detected? I spent countless hours trying to debug the problem, but I have hit a road block. Need help.
Last edited on
What does BoundingBox() do? I would guess that you are returning only the result of the last collision, but I can't know without seeing the code.
Thanks for the response Zhuge, here is the implementation:

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
bool BoundingBox(Rect & Object1, vector<Rect> & Object2)
{
	OrientedBoundingBox OBB1(Object1);   // <- The definitions for the constructors are above.
	OrientedBoundingBox OBB2(Object2);

	sf::Vector2f Axis[4] = 
	{
		sf::Vector2f(OBB1.Points[1].x - OBB1.Points[0].x, OBB1.Points[1].y - OBB1.Points[0].y),
		sf::Vector2f(OBB1.Points[1].x - OBB1.Points[2].x, OBB1.Points[1].y - OBB1.Points[2].y),
		sf::Vector2f(OBB2.Points[0].x - OBB2.Points[3].x, OBB2.Points[0].y - OBB2.Points[3].y),
		sf::Vector2f(OBB2.Points[0].x - OBB2.Points[1].x, OBB2.Points[0].y - OBB2.Points[1].y)
	
	};

	for(int i = 0; i < 4; i++)
	{
		float MinOBB1, MaxOBB1, MinOBB2, MaxOBB2;

		OBB1.ProjectOntoAxis(Axis[i], MinOBB1, MaxOBB1);
		OBB2.ProjectOntoAxis(Axis[i], MinOBB2, MaxOBB2);

		if(!((MinOBB2 <= MaxOBB1) && (MaxOBB2 >= MinOBB1)))
			return false;
	
	}

	return true;
}

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
        OrientedBoundingBox(vector<Rect> & rect)
	{
		for(int i = 0; i < rect.size(); i++)
		{
			sf::Transform tran = rect[i].getTransform();

			Points[0] = tran.transformPoint(0.0f, 0.0f);
			Points[1] = tran.transformPoint(rect[i].getSize().x, 0.0f);
			Points[2] = tran.transformPoint(rect[i].getSize().x, rect[i].getSize().y);
			Points[3] = tran.transformPoint(0.0f, rect[i].getSize().y);
		
		}
	
	}


You are looping over the vector and settings Points[0] - Points[3] equal to one of the boxes each time (while overwriting whatever was there before). At the end all that is left is the final box.

You have to move where you have your for loop. Maybe put it in the BoundingBox function and create one OrientedBoundingBox at a time from the vector. The algorithm itself is fine.
Thanks for the help, James2250 and Zhuge, you guys have been a huge help.
Last edited on
Topic archived. No new replies allowed.