0
\$\begingroup\$

I am trying to create a collision detection system between block using this code:

bool simpleCollisionDetection(vector3df new_player_pos, vector3df block) {
int static col = 0; // used to see how many total collisions there have been

// each if statement represents collision detection of each corner of the player
if((floor(new_player_pos.X/10) == floor(block.X/10) && floor(new_player_pos.Z/ 10) == floor(block.Z/ 10)) && floor(new_player_pos.Y/10) - 3 == floor(block.Y/10)) {
    std::cout << "collision! 1 \n";
    col++;
    return true;
}

if((floor(new_player_pos.X/10) + 1 == floor(block.X/10) && floor(new_player_pos.Z/ 10) == floor(block.Z/ 10)) && floor(new_player_pos.Y/10) - 3 == floor(block.Y/10)) {
    std::cout << "collision! 2\n";
    col++;
    return true;
}

if((floor(new_player_pos.X/10) == floor(block.X/10) && floor(new_player_pos.Z/ 10) + 1 == floor(block.Z/ 10)) && floor(new_player_pos.Y/10) - 3 == floor(block.Y/10)) {
    std::cout << "collision! 3\n";
    col++;
    return true;
}

if((floor(new_player_pos.X/10) + 1 == floor(block.X/10) && floor(new_player_pos.Z/ 10) + 1 == floor(block.Z/ 10)) && floor(new_player_pos.Y/10) - 3 == floor(block.Y/10)) {
    std::cout << "collision! 4\n";
    col++;
    return true;
}

return false; // false = no collision happened!

}

and player movement:

if(receiver.IsKeyDown(irr::KEY_KEY_W)) {
        if(rotation >= 0.0 && rotation <= 90.0) {
            float rot = rotation / 90.0;

            player->setPosition(vector3df(cam_x + 1*rot, cam_y - 2, cam_z + 1*(1 - rot)));

            bool col = false; // collision boolean, if false then there has not been a collision
            for(int i = 0; i < objc.size(); i++) { // iterate through all objects (cubes) and check if there has been a collision
                col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                if(col) { // there is no need to check other blocks if there has happened a collision.
                    break; // without break the collision boolean would be set to false and only collision for the last added object would be detected.
                }
            }


            while(col) { // if a collision has happened, move the player in the opposite moving direction untill the player is outside and no collision happens
                player->setPosition(vector3df(player->getPosition().X - 0.05*rot*1.5, player->getPosition().Y, player->getPosition().Z - 0.05*(1-rot)));
                for(int i = 0; i < objc.size(); i++) {
                    col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                    if(col) {
                        break;
                    }
                }
            }
            // when there is no collision move the camera to the player position but slightly back
            // if a collision happened and player is not moved back, then the player will not be able to move alongside walls.
            if(!col)
                cam->setPosition(vector3df(player->getPosition().X - 0.1, player->getPosition().Y + 2, player->getPosition().Z - 0.1));
            }

        } else if(rotation > 90.0 && rotation <= 180.0) {
            float rot = (rotation - 90) / 90.0;

            player->setPosition(vector3df(cam_x + 1*(1 - rot), cam_y - 2, cam_z - 1*rot));

            bool col = false;
            for(int i = 0; i < objc.size(); i++) {
                col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                if(col) {
                    break;
                }
            }

            while(col) {
                player->setPosition(vector3df(player->getPosition().X - 0.05*(1-rot), player->getPosition().Y, player->getPosition().Z + 0.05*rot*1.5));
                for(int i = 0; i < objc.size(); i++) {
                    col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                    if(col) {
                        break;
                    }
                }
            }

            if(!col) {
                cam->setPosition(vector3df(player->getPosition().X - 0.1, player->getPosition().Y + 2, player->getPosition().Z + 0.1));
            }
        } else if(rotation > 180.0 && rotation <= 270.0) {
            float rot = (rotation - 180) / 90.0;

            player->setPosition(vector3df(cam_x - 1*rot, cam_y - 2, cam_z - 1*(1 - rot)));

            bool col = false;
            for(int i = 0; i < objc.size(); i++) {
                col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                if(col) {
                    break;
                }
            }

            while(col) {
                player->setPosition(vector3df(player->getPosition().X + 0.05*rot*1.5, player->getPosition().Y, player->getPosition().Z + 0.05*(1-rot)));
                for(int i = 0; i < objc.size(); i++) {
                    col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                    if(col) {
                        break;
                    }
                }
            }

            if(!col) {
                cam->setPosition(vector3df(player->getPosition().X + 0.1, player->getPosition().Y + 2, player->getPosition().Z) + 0.1);
            }
        } else if(rotation > 270.0 && rotation <= 360.0) {
            float rot = (rotation - 270) / 90.0;

            player->setPosition(vector3df(cam_x - 1*(1 - rot), cam_y - 2, cam_z + 1*rot));

            bool col = false;
            for(int i = 0; i < objc.size(); i++) {
                col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                if(col) {
                    break;
                }
            }

            while(col) {
                player->setPosition(vector3df(player->getPosition().X + 0.05*(1-rot), player->getPosition().Y, player->getPosition().Z - 0.05*rot*1.5));
                for(int i = 0; i < objc.size(); i++) {
                    col = simpleCollisionDetection(player->getPosition(), objc[i]->getPosition());
                    if(col) {
                        break;
                    }
                }
            }

            if(!col) {
                cam->setPosition(vector3df(player->getPosition().X + 0.1, player->getPosition().Y + 2, player->getPosition().Z - 0.1));
            }
        }
    }

Everything in this game is 10x10x10 3D cubes, including the player. The reason I divide the position of the blocks and the player is because I want to have a sort of "3D grid" of all entities. By dividing by 10 I get their "block position", which is distict from exact coordinates but this type of detection creates a more easy to use 3D grid of all the entities. The reason why in the collision detection the Y axis is reduced by 3 is because the camera is 3 blocks higher than the player. Without that reduction I'd be collision checking an entity 3 block units above my player, which is not what I want.

I do not want to use an outside collision engine or physics engine because I want my code to be minimal. I have read and read and read about different collision detection systems such as AABB, contact caching, prediction, sleeping, moving back, different types of collision-resolutions, etc. What I want is not the theory, I have recieved and takes part of ALL the theory. I want something concrete, some code, because for some reason I am unable to apply the theory.

I have yet to find a code snippet example of 3d collision detection of cubes, it's not on google, not on youtube, not on stackexchange. There are some examples but they are either based on a library, which I do not want to use, or they are related to "bouncy" blocks and push back force from impact.

I've tried to come up with a collision detection system myself, this is probably my 8th way of doing this. I have 7 more ways of collision detection in my code but this is my latest and the one that works the best. The issue with this code is that my player moves alongside the wall even when I direct the movement directly into the block wall.

tl;dr why does my code result in my 3D 10x10x10 cube character to move alongside my 3D 10x10x10 cube wall when they collide?

bonus for anyone who gives me a concrete example of code instead of theory, since I can't find any examples fitting my description: no engine besides rendering engine, no bouncy blocks, just STOP the collision in one axis.

Also: I am using Irrlicht 3D rendering engine on Windows 8 using code::blocks if that is relevant in any way.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.