# Vector collision detection only on one instance?

This topic is 2279 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey guys, ive been working on some basic code for a simple game engine, it seems to be going really well, I have some collision detection and it works 100% correctly, but I have a vector of game entities, and i have written a for loop to go look through them and check for collision, but it only seems to check on the last entity

Here is the code for my 4 wall entities

 eEntity wall1; eEntity wall2; eEntity wall3; eEntity wall4; wall1.setPosition(10,10); wall2.setPosition(40,10); wall3.setPosition(70,10); wall4.setPosition(70,40); std::vector<eEntity> walls; walls.push_back(wall1); walls.push_back(wall2); walls.push_back(wall3); walls.push_back(wall4); 

Here is the code for my while statement,

 while (quit == false) { fps.start(); while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { quit = true; } //Check collisions //Handle Inputs gamePlayer.handleInput(event); } //Update //Check Collision for(int i=0;i<walls.size();i++) { gamePlayer.takeRectCollision(walls.at(i).rtnCollision()); } gamePlayer.update(); //Clear screen SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); //Draw SDL_BlitSurface(gamePlayer.draw(),NULL,screen,&gamePlayer.rtnPos()); for(int i=0;i<walls.size();i++) { SDL_BlitSurface(walls.at(i).draw(),NULL,screen,&walls.at(i).rtnPos()); } if (SDL_Flip(screen) == -1) { return 1; } if( fps.rtnTicks() < 1000 / framerate ) { SDL_Delay( ( 1000 / framerate ) - fps.rtnTicks() ); } } 

As i said my code compiles with my headers and code, but the collision detection is only checked on the last element in the vector

but also my draw for loop works, and draws all 4 walls.

Anyone have a idea on my error?

##### Share on other sites
I cannot help you if you don't show up the code of takeRectCollision, rtnnCollision and update, all methods of gamePlayer.

##### Share on other sites
Ok let me get the code

Code for takeRectCollision
 void eEntity::takeRectCollision(SDL_Rect &rectTake) { collisionTemp = rectTake; } 

Return collision
 SDL_Rect eEntity::rtnCollision() { SDL_Rect temp; temp.x = pos.x; temp.y = pos.y; temp.w = width; temp.h = height; return temp; } 

Update
 void eEntity::update() { pos.x += xVel; if(collision.rectTorectCollision(pos.x,pos.y,width,height,collisionTemp.x,collisionTemp.y,collisionTemp.w,collisionTemp.h)) { pos.x -= xVel; } pos.y += yVel; if(collision.rectTorectCollision(pos.x,pos.y,width,height,collisionTemp.x,collisionTemp.y,collisionTemp.w,collisionTemp.h)) { pos.y -= yVel; } } 

Thats most of the methods from eEntity, also the gamePlayer is a Entity

##### Share on other sites
In your for loop you go through and call takeRectCollision for each wall...
Each time you call that the collisionTemp is replaced; however, you only check against that collisionTemp object during the update method, which is only called after you called takeRectCollision all 4 times.

In essence you are only checking for one collision (in update method) against the last SDL_Rect to which collisionTemp was set. What you need to do is check for a collision against every collisionTemp that you set.

Does that make sense?

##### Share on other sites
it does indeed, so i need to call the update after each collision , there most be a better way, any idea?

##### Share on other sites
I don't see why you wouldn't call update each time, but another way would be to store the temps in an array, one set for each actual collision, and process them all at once during update.

##### Share on other sites
For each object that i want to check for collision i could make a Vector in the player object, this vector will hold SDL_Rect's and then use them in the collision detection in the player, that sound ok?

##### Share on other sites
Yeup, something like that. You clear the vector each frame, add only the data for walls that actually collide with the player, then parse these in the update method.

##### Share on other sites
Ok so lets go for this, i make a vector of SDL_Rects, in the update in the player object, it will go through each one, but there is a problem, if it was to collide with the first block but lets say it was hitting the 4th block with this still function correctly?

I just did some code and it kinda works...abit but acts weird
This is the code in main
 for(int i=0;i<walls.size();i++) { gamePlayer.takeRectCollision(walls.at(i).rtnCollision()); } 

This just takes in a SDL_Rect and adds it to a vector
Here is the code for takeRectCollision
 void eEntity::takeRectCollision(SDL_Rect &rectTake) { rects.push_back(rectTake); } 

And here is the code for the update
 void eEntity::update() { for(int i = 0;i<rects.size();i++) { if(collision.rectTorectCollision(pos.x,pos.y,width,height,rects.at(i).x,rects.at(i).y,rects.at(i).w,rects.at(i).h)) { pos.x -= xVel; } if(collision.rectTorectCollision(pos.x,pos.y,width,height,rects.at(i).x,rects.at(i).y,rects.at(i).w,rects.at(i).h)) { pos.y -= yVel; } } pos.x += xVel; pos.y += yVel; } 

But the collision doesnt seem to go very well

What happens now is my player box gets stuck inside the other boxs, and then just messing up

its ok, i just update the update code and here it is
 void eEntity::update() { pos.x += xVel; for(int i = 0;i<rects.size();i++) { if(collision.rectTorectCollision(pos.x,pos.y,width,height,rects.at(i).x,rects.at(i).y,rects.at(i).w,rects.at(i).h)) { pos.x -= xVel; } } pos.y += yVel; for(int i = 0;i<rects.size();i++) { if(collision.rectTorectCollision(pos.x,pos.y,width,height,rects.at(i).x,rects.at(i).y,rects.at(i).w,rects.at(i).h)) { pos.y -= yVel; } } } 

it works fine now, cheers guys

##### Share on other sites
If you're making an "engine" then you need to be extremely flexible. You shouldn't just be checking the player against some objects, but rather all collidible objects against each other, and provide some kind of mask to the user of the Engine to define if he wants one object to collide with another.

So, for example, you have a game with many enemies shooting bullets at a player, and there's walls and there are items the player can pick up. Well, you want the player to collide with the wall, enemies, enemy's bullets, and the items, but not his own bullets. You want the enemies to collide with other enemies, the player, the player's bullets and the wall, but not with enemy's bullets nor items.

Each of these objects should inherit from a general Physical Object (that has physical dimensions, positioning in the world, and movement attributes. You provide a method for the user to determine what can collide with what (bit-masks are a common method as well as layers), and then place each physical object into it's own types vector, and then compare each object in those vectors to the vector of objects that they collide with.

Example.
 enum { FIRST_COLLIDE_TYPE = 1, PLAYER_COLLIDE_TYPE = FIRST_COLLIDE_TYPE , ENEMY_COLLIDE_TYPE, PLAYER_BULLET_COLLIDE_TYPE, ENEMY_BULLET_COLLIDE_TYPE, MAX_COLLIDE_TYPE }; pulic ICollisionHandler { virtual ~ICollisionHandler () {}; virtual HandleCollision(TPhysicalObject &ObjectCollidiedWith); }; class TPhysicalObject : public ICollisionHandler { public: double x,y , width, height; double xVelocty, yVelocity; unsigned int collideType; unsigned int collideMask; // gets called when this object hits another one HandleCollision(TPhysicalObject &ObjectCollidiedWith); }; // assume there is a class for Player, Enemy, PlayerBullet and EnemyBullet // defined like this class TPlayer : public PhysicalObject // In Player constructor, you set the bitmask to all the objects you can collide with TPlayer::TPlayer() { ... collideMask = (1 << ENEMY_COLLIDE_TYPE) | (1 << ENEMY_BULLET_COLLIDE_TYPE); } // same in other constructors // in your engine header, you could have: std::map CollisionMap<unsigned int, std::vector<TPhysicalObject&> >; // and in the /ccp file void MyEngine::AddCollisionObject(TPhysicalObject &object) { // add to proper , make it a map CollisionMap[object.collideType].push_back(object); } // later, when checking for collisions, you'd do this void MyEngine::Update() { // loop through every CollisionMap, and check collisions with other maps // in the objects collision mask for (itMap = CollisionMap.begin(); itMap != CollisionMap.end(); itMap++) { for (itObject = itMap->begin(); itObject != itMap->end(); itObject++) { for (int i = itObject->collideType+1 ; i < MAX_COLLIDE_TYPE; it++) { if (itObject->collideMask & (1 << i)) { // loop through every object in CollisionMap vector and check for Collides // if they collide, tell each of them they collided with the other if (Collides(*itObject, *itCheckObject) { itObject->HandleCollision(*itCheckObject); itCheckObject->HandleCollision(*itObject); } } } } } } 

OK, I spent WAY too much time on that, but that's an idea of how I'd do it.

• 48
• 12
• 10
• 10
• 9
• ### Forum Statistics

• Total Topics
631375
• Total Posts
2999657
×