Search code examples
c++responsecollisionirrlicht

How to move multiple rectangles as collision response?


I'm trying to make a game (using irrlicht engine with c++) where you can trap your enemy using boxes. But I just don't get how to detect what should be moved when a collision between the user and one or more boxes is detected. Another thing is that there will also be some objects called bricks which will be able to block movements.

Since I'm not very good in explaining things, I included an image, so it will hopefully clarify what I mean: alt text
(source: jrahmati.info)

I tried several things with my code but without success. So I really hope someone will take the effort to give an answer to this issue. Thanks in advance. By the way, I don't need the answer necessarily in c++, java or .Net languages are also ok.

For anyone interested in the code:

content of bool Game::tryMove(user, dir) which tries to move everthing away from the player

bool thereIsCollision = false;
bool undoMovements = false;
bool userCollision = false;
do{
    thereIsCollision = false;
    for (int i = 0; i < totalObjects; i++) {
        //First check if object hits the user
        if(gameObjects[i].hits(user)){
            if (gameObjects[i]->isMovable()) {
                MovableObject* mObject = (MovableObject*) gameObjects[i];
                mObject->move(dir);
                mObject->setPushVector(dir);
                userCollision = true;
                //thereIsCollision = true;
            }
            else{
                undoMovements = true;
                thereIsCollision = false; //To break do-while loop
                userCollision = true;
                break;
            }
        }
    }
    if(undoMovements)
        break;
    for (int i = 0; i < totalObjects; i++) {
        //Then check if objects hit each other
        for (int i2 = 0; i2 < totalObjects; i2++) {
            if(i == i2)
                continue;
            if (gameObjects[i2].hits(gameObjects[i])){
               //thereIsCollision = true;
               if(gameObjects[i]->isMovable() && gameObjects[i2]->isMovable()){
                   MovableObject* mObject = (MovableObject*) gameObjects[i];
                   MovableObject* mObject2 = (MovableObject*) gameObjects[i2];
                   if(mObject->getPushVector().X > 0 
                           || mObject->getPushVector().Y > 0 
                           || mObject->getPushVector().Z > 0){
                       mObject2->move(mObject->getPushVector());
                       mObject2->setPushVector(mObject->getPushVector());
                       mObject->setPushVector(irr::core::vector3df(0, 0, 0));
                   }
                   else if(mObject2->getPushVector().X > 0 
                           || mObject2->getPushVector().Y > 0 
                           || mObject2->getPushVector().Z > 0){
                       mObject->move(mObject2->getPushVector());
                       mObject->setPushVector(mObject2->getPushVector());
                       mObject2->setPushVector(irr::core::vector3df(0, 0, 0));
                   }
               }
               else{
                   undoMovements = true;
                   thereIsCollision = false; //To break do-while loop
                   break;
               }
           }
        }
    }
}while(thereIsCollision);

for (int i = 0; i < totalObjects; i++) {
    if (gameObjects[i]->isMovable()) {
        MovableObject* mObject = (MovableObject*) gameObjects[i];
        if(undoMovements){
            // Resets position of gameObject to its previous one
            mObject->undoMovement();
        }
        else{
            // confirms movement(i.e. prevPosition=curPosition)
            mObject->confirmMovement();
        }
    }
}
return !(userCollision);

Solution

  • Is this a sort of Sokoban game where the player can move in 8 directions, and is able to move several boxes at once? Is the play field viewed from birds eye view like in Sokoban, or are they falling boxes that we see in the example (side view, like in Tetris)? Is the friction between boxes and player infinite (in another words, is it forbidden for the box that player is touching to slide away from direction the player is moving, when it moves diagonally)? Is the friction between two boxes infinite?

    I couldn't focus on your code, but here's my 2cents algorithm. The algorithm implies that friction between any two objects is infinite.

    When player moves you need to establish which movable objects may be affected. Put the ones the player is touching in the moving direction into some search stack, then for each item in the search stack repeat the search process by putting more objects into it. Finally you'll run out of movable objects. If at any point you stumble upon a non-movable object then the player can't move as well (because of infinite friction rule), and so nothing moves. If there are no non-movable objects involved then move all objects in the stack by one grid unit.