Thread: I dont understand why this collision doesnt work

  1. #1
    Registered User
    Join Date
    Jul 2019
    Posts
    34

    I dont understand why this collision doesnt work

    I am working on a little console game, just messing around with trying to create a 2D game map and be able to move on it and I succeeded in both regards, however, in game worlds you encounter objects you cant go through, so I decided to add a boulder as a test and hard code its position and collision data just to test if the collision works, then go back and try to figure out how to insert any collidable there.

    I cannot seem to get it to work and I dont understand why because the position where the player is not supposed to be able to move is a hard coded position, however after adding all the collision data the player will no longer move on the map.

    When i had only collision data for moving up, it would stop when it hit the boulder, but something about adding the other collision data makes it not work, i'm not sure why.

    What am I doing wrong?


    Code:
    #include <iostream>#include <string>
    #include <vector>
    
    
    using std::cout;
    using std::endl;
    using std::string;
    using std::vector;
    using std::cin;
    
    int main()
    {   
    
    
        int mapX{10};
        int mapY{16};
        
        int playerX{3};
        int playerY{3};
        
        char player{'O'};
        char mapTile{'*'};
        char boulder{'@'};
        
        //Why does this need another vector as a second argument?
        vector<vector<char> > gameMap(mapX, vector<char>(mapY, mapTile));
        
        bool endGame = false;
        int choice{ 0 };
        
        //Map issue
        //Characters last position still stays drawn on screen.
        while(endGame != true)
        {
            //Generate a map
            for(int i = 0; i < mapX; i++)
            {
                for(int j = 0; j < mapY; j++)
                {
                    //Redraw map screen or else player/enemy last positions will be kept after moving.
                    gameMap[i][j] = mapTile;
                    gameMap[6][6] = boulder;
                    //Draw player
                    gameMap[playerX][playerY] = player;
                    //Draw map to screen
                    cout << gameMap[i][j];
                }
                cout << endl;
            }
            cout << "Player X pos: " << playerX << endl;
            cout << "Player Y pos: " << playerY << endl;
            cout << "1) UP" << endl;
            cout << "2) DOWN" << endl;
            cout << "3) LEFT" << endl;
            cout << "4) RIGHT" << endl;
            cin >> choice;
            
            //Movement
            //Collision problem
            //How to get position of boulder or any other collidable?
           if(choice == 1)
           {
               if(playerX -= 1 == gameMap[6][6])
               {
                   cout << "Cannot move Up anymore." << endl;
               }
               else if(playerX -= 1 != gameMap[6][6])
               {
                   playerX -= 1;
               }
           }
           if(choice == 2)
           {
               if(playerX += 1 == gameMap[6][6])
               {
                   cout << "Cannot move Down anymore." << endl;
               }
               else if(playerX += 1 != gameMap[6][6])
               {
                   playerX += 1;    
               }
           }
           if(choice == 3)
           {
               if(playerY -= 1 == gameMap[6][6])
               {
                   cout << "Cannot move Left anymore." << endl;
               }
               else if(playerY -= 1 != gameMap[6][6])
               {
                   playerY -= 1;
               }
           }
           if(choice == 4)
           {
               if(playerY += 1 == gameMap[6][6])
               {
                   cout << "Cannot move Right anymore." << endl;
               }
               else if(playerY += 1 != gameMap[6][6])
               {
                   playerY += 1;
               }
           }
           
           cin.get();
        }
        
     
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,085
    Code:
    #include <iostream>
    #include <vector>
     
    using std::cout;
    using std::cin;
    using std::vector;
     
    int main()
    {   
        enum { Player='O', MapTile='*', Boulder='@' };
        const int Rows{10}, Cols{16};
        const int BoulderRow{6}, BoulderCol{6};
     
        vector<vector<char>> map(Rows, vector<char>(Cols, MapTile));
     
        // Initialize map.
        for (int r = 0; r < Rows; ++r)
            for (int c = 0; c < Cols; ++c)
                map[r][c] = MapTile;
        map[row][col] = Player;
        map[BoulderRow][BoulderCol] = Boulder;
     
        int row{3}, col{3};  // Player position.
        bool endGame = false;
     
        while (!endGame)
        {
            // Draw map.
            for (int r = 0; r < Rows; ++r)
            {
                for (int c = 0; c < Cols; ++c)
                    cout << map[r][c] << ' ';
                cout << '\n';
            }
     
            cout << "Player (Row,Col): " << row << ' ' << col << '\n';
            cout << "w) UP  s) DOWN  a) LEFT  d) RIGHT  q) QUIT\n";
            char choice {};
            cin >> choice;
     
            // Erase player.
            map[row][col] = MapTile;
     
            switch (choice)
            {
            case 'w':
                if (row == 0 || map[row - 1][col] == Boulder)
                    cout << "Cannot move Up.\n";
                else
                    --row;
                break;
            case 's':
                if (row == Rows - 1 || map[row + 1][col] == Boulder)
                    cout << "Cannot move Down.\n";
                else
                    ++row;
                break;
            case 'a':
                if (col == 0 || map[row][col - 1] == Boulder)
                    cout << "Cannot move Left.\n";
                else
                    --col;
                break;
            case 'd':
                if (col == Cols - 1 || map[row][col + 1] == Boulder)
                    cout << "Cannot move Right.\n";
                else
                    ++col;
                break;
            case 'q':
                endGame = true;
                break;
            default:
                cout << "Please enter w, s, a, d, or q.\n";
            }
     
            // Redraw player.
            map[row][col] = Player;
        }
    }
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    1,085
    I just realized that the "Initialize map" code needs to be after the declarations of row and col! (I must've moved it without testing. )
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,294
    Quote Originally Posted by john.c View Post
    I just realized that the "Initialize map" code needs to be after the declarations of row and col! (I must've moved it without testing. )
    You need to learn from those sneaky teachers and claim that you were just checking to see if the students were paying attention.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Jul 2019
    Posts
    34
    Awesome! thank you!

  6. #6
    Registered User
    Join Date
    Jul 2019
    Posts
    34
    How do I get this to check against each object in the vector and if it finds one then it adds collision to it?

    I added a vector with objects and made an iterator to iterate over it but i dont know how to loop through it because of the if statement, I know how to loop through a container using an iterator, just not how to use it to compare to the players position in the first if statement checking for up collision, I've tried a bunch of things and i cannot get it working correctly. It somewhat works, but it only checks the first element in the vector since I have objects.begin() but not sure where to do objects.end() to loop through the entire thing.

    I'm trying to make it so that i can create the map the way I want it and then use the vector with the objects in it to plug into the collision which will allow me to have bounds for the objects in said vector.

    Code:
    #include <iostream>#include <vector>
    #include <iterator>
    
    
    using std::cout;
    using std::endl;
    using std::cin;
    using std::vector;
    using std::iterator;
    
    
    int main()
    {
        const int mapX{ 10 };
        const int mapY{ 16 };
        const int boulderXPos{ 6 };
        const int boulderYPos{ 6 };
        const char boulder{ '@' };
        const char player{ 'O' };
        const char mapTile{ '*' };
    
    
        vector<vector<char>> map(mapX, vector<char>(mapY, mapTile));
    
    
        //Create list of collidables
        vector<char> objects{ 'x', '&' };
        //Gets first element but how do i get last too?
        vector<char>::iterator itr = objects.begin();
        //How do i use this to get the end of the iterator in the if statement????
        vector<char>::iterator itr2 = object.end();
        int playerXPos{ 6 };
        int playerYPos{ 4 };
    
    
        // Initialize map.
        for (int r = 0; r < mapX; ++r)
            for (int c = 0; c < mapY; ++c)
                map[r][c] = mapTile;
        map[playerXPos][playerYPos] = player;
        map[6][6] = boulder;
        map[7][7] = boulder;
        map[4][4] = 'x';
        map[5][5] = '&';
    
    
        bool endGame = false;
    
    
        while (!endGame)
        {
            // Draw map.
            for (int x = 0; x < mapX; ++x)
            {
                for (int y = 0; y < mapY; ++y)
                    cout << map[x][y] << ' ';
                cout << '\n';
            }
    
    
            cout << "player X: " << playerXPos << endl;
            cout << "player Y: " << playerYPos << endl;
            cout << "w) UP  s) DOWN  a) LEFT  d) RIGHT  q) QUIT\n";
            char choice{};
            cin >> choice;
    
    
            // Erase player.
            map[playerXPos][playerYPos] = mapTile;
    
    
            switch (choice)
            {
            case 'w':
                //collision will only find first item in iterator to check against
                //because its only starting at the beginning and not going to the end
                if (playerXPos == 0 || map[playerXPos - 1][playerYPos] == *itr)
                    cout << "Cannot move Up.\n";
                else
                    --playerXPos;
                break;
            case 's':
                if (playerXPos == mapX - 1 || map[playerXPos + 1][playerYPos] == boulder)
                    cout << "Cannot move Down.\n";
                else
                    ++playerXPos;
                break;
            case 'a':
                if (playerYPos == 0 || map[playerXPos][playerYPos - 1] == boulder)
                    cout << "Cannot move Left.\n";
                else
                    --playerYPos;
                break;
            case 'd':
                if (playerYPos == mapY - 1 || map[playerXPos][playerYPos + 1] == boulder)
                    cout << "Cannot move Right.\n";
                else
                    ++playerYPos;
                break;
            case 'q':
                endGame = true;
                break;
            default:
                cout << "Please enter w, s, a, d, or q.\n";
            }
    
    
            // Redraw player.
            map[playerXPos][playerYPos] = player;
        }
    }
    Last edited by ChayHawk; 02-11-2021 at 06:54 AM.

  7. #7
    Registered User
    Join Date
    Dec 2017
    Posts
    1,085
    Maybe something like this:
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
     
    using std::cout;
    using std::cin;
    using std::string;
    using std::vector;
     
    enum { Player='O', MapTile='*' };
    const int Rows{10}, Cols{16};
    const string collidables{ "@x&" };
    enum { Boulder, Wall, ClosedDoor };
     
    bool collision(char ch)
    {
        return collidables.find(ch) != string::npos;
    }
     
    void init_map(vector<vector<char>>& map)
    {
        for (int r = 0; r < Rows; ++r)
            for (int c = 0; c < Cols; ++c)
                map[r][c] = MapTile;
        map[6][6] = collidables[Boulder];
        map[7][7] = collidables[Boulder];
        map[4][4] = collidables[Wall];
        map[5][5] = collidables[ClosedDoor];
    }
     
    void draw_map(const vector<vector<char>>& map)
    {
        for (int r = 0; r < Rows; ++r)
        {
            for (int c = 0; c < Cols; ++c)
                cout << map[r][c] << ' ';
            cout << '\n';
        }
    }
     
    int main()
    {
        vector<vector<char>> map(Rows, vector<char>(Cols, MapTile));
        init_map(map);
      
        int row{3}, col{3};  // Player position.
     
        for (bool endGame{false}; !endGame; )
        {
            // Set player.
            map[row][col] = Player;
     
            draw_map(map); 
     
            cout << "Player (Row,Col): " << row << ' ' << col << '\n';
            cout << "w) UP  s) DOWN  a) LEFT  d) RIGHT  q) QUIT\n";
            char choice {};
            cin >> choice;
     
            // Remove player.
            map[row][col] = MapTile;
     
            switch (choice)
            {
            case 'w':
                if (row == 0 || collision(map[row - 1][col]))
                    cout << "Cannot move Up.\n";
                else
                    --row;
                break;
            case 's':
                if (row == Rows - 1 || collision(map[row + 1][col]))
                    cout << "Cannot move Down.\n";
                else
                    ++row;
                break;
            case 'a':
                if (col == 0 || collision(map[row][col - 1]))
                    cout << "Cannot move Left.\n";
                else
                    --col;
                break;
            case 'd':
                if (col == Cols - 1 || collision(map[row][col + 1]))
                    cout << "Cannot move Right.\n";
                else
                    ++col;
                break;
            case 'q':
                endGame = true;
                break;
            default:
                cout << "Please enter w, s, a, d, or q.\n";
            }
        }
    }
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,085
    Quote Originally Posted by laserlight View Post
    You need to learn from those sneaky teachers and claim that you were just checking to see if the students were paying attention.
    Clearly I still have something to learn about guruship.
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  9. #9
    Registered User
    Join Date
    Jul 2019
    Posts
    34
    hmm, thats an interesting way to do it actually. However I still would like the vector approach because I plan to start using SFML soon and I want to create a simple 2D game and it would require the use of vectors to hold the tiles and other resources. What I'm doing it learning how to do the stuff I would need to do for the game with graphics like collision, drawing a map, loading resources into a vector etc so that when I go from text graphics to picture graphics, it wont be that difficult of a transition. With the map drawing and collision, I can pretty much just copy SFML code over to it without changing too much. For the sprite resources they will need to be loaded into a vector then set on the map so using a vector of characters would be pretty similar.

    I probably should have explained all that to begin with, so my apologies.

  10. #10
    Registered User
    Join Date
    Dec 2017
    Posts
    1,085
    Since it's easy to change it to vector<char> I'll leave that to you.
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. dont know how why this doesnt work
    By I C everything in forum C++ Programming
    Replies: 6
    Last Post: 09-03-2019, 08:51 AM
  2. need help dont understand
    By txfog in forum C++ Programming
    Replies: 6
    Last Post: 06-14-2013, 07:38 AM
  3. Please help me i dont know why this doesnt work
    By Mr.who in forum C Programming
    Replies: 6
    Last Post: 11-25-2011, 11:32 AM
  4. I dont understand why this wouldn't work
    By We'reGeeks in forum C Programming
    Replies: 28
    Last Post: 03-02-2011, 03:26 AM
  5. dont understand VS.NET
    By Qui in forum Windows Programming
    Replies: 6
    Last Post: 10-15-2003, 07:36 PM

Tags for this Thread