简体   繁体   中英

How can I add colliders for my adventure game in cmd with 2d array defining the map in c++?

I am currently writing the beginning structure of a 2d cmd adventure game. If you look at the provided code, I have my tiles stored in a struct, and I have a bool for the collider.

My original idea is to have 4 'nodes' around the character and there will be an if statement in the following move commands checking the position of the node and seeing if there is a collider tile to see if you can move there or not.

I'm stuck because I am storing the tiles as a char "barrier.type", and I want to only read "barrier.type" not the char data "#" that is currently being stored in it. The only way I thought of doing this is making the position a string and then deleting the last 4 letters of it and adding collider, but I don't know how that will work because they are two different data types unless I can somehow get a char to a string. In that case I think if I got it to turn into a string it would make "#" a string.

If someone has a better idea for checking colliders or how to make my original idea my current player and tile system is very flexible and I am open to a wide variety of details.

Code:

using namespace std;

void drawArea();
//void getInput();
void resizeWindow();

bool gameRunning = true;
int position[2] = { 8,10 };
//char character = '@';
int aboveNode[2] = { 9,10 };
int belowNode[2] = { 7,10 };
int leftNode[2] = { 8,9 };
int rightNode[2] = { 8,11 };

struct tileType
{
    enum class Tile { air, wallside, walltop, wallbottom, barrier, };
    Tile x;
    char type;
    bool collider;
};
//// tiles////
 tileType barrier = {
    tileType::Tile::barrier,
    '#',
    true,
};
 tileType air = {
    tileType::Tile::air,
    ' ',
    false,


 };
////player control////
class Player {
    public:

        char character = '@';

        int playerX = position[1];
        int playerY = position[0];



        void getInput() {
            if (GetAsyncKeyState(VK_UP)) {

                position [0] -= 1;
                aboveNode[0] -= 1;
                belowNode[0] -= 1;
                leftNode [0] -= 1;
                rightNode[0] -= 1;

            }
            else if (GetAsyncKeyState(VK_DOWN)) {
                position [0] += 1;
                aboveNode[0] += 1;
                belowNode[0] += 1;
                leftNode [0] += 1;
                rightNode[0] += 1;
            }
            else if (GetAsyncKeyState(VK_LEFT)) {
                position [1] -= 1;
                aboveNode[1] -= 1;
                belowNode[1] -= 1;
                leftNode [1] -= 1;
                rightNode[1] -= 1;

            }
            else if (GetAsyncKeyState(VK_RIGHT)) {
                position [1] += 1;
                aboveNode[1] += 1;
                belowNode[1] += 1;
                leftNode [1] += 1;
                rightNode[1] += 1;

            }
        }
    private:
        void checkNodeA() {
            //string mapData = map[aboveNode[0]][aboveNode[1]];

        }
        void checkNodeB() {
            //map[belowNode[0]][belowNode[1]];

        }
        void checkNodeL() {
            //map[leftNode[0]][leftNode[1]];

        }
        void checkNodeR() {
            //map[rightNode[0]][rightNode[1]];

        }
};




void setup() {


}








char map[33][34] = { { barrier.type,barrier.type, barrier.type, barrier.type, barrier.type,barrier.type, barrier.type,barrier.type,barrier.type, barrier.type,barrier.type, barrier.type, barrier.type, '#', '#','#', '#','#','#', '#', '#', '#', '#', '#', '#','#', '#','#','#', '#', '#', '#', '#', '#' },
{ '#', '|', '-', '-', '-','-', '|',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', '|', ' ', ' ', ' ',' ', '|',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', '|', '[', ']', ' ',' ', '|',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', '|', '_', '_', '_','_', '|',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', '|', '|',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', '-', '-',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', ' ', ' ',' ', ' ',' ',' ', ' ', ' ', ' ', ' ', '#' },
{ '#', '#', '#', '#', '#','#', '#','#','#', '#','#', '#', '#', '#', '#','#', '#','#','#', '#', '#', '#', '#', '#', '#','#', '#','#','#', '#', '#', '#', '#', '#' } };

void drawArea() {
    Player player;
    for (int y = 0; y < 33; y++) {
        for (int x = 0; x < 34; x++) {
            if (y == player.playerY && x == player.playerX) {
                cout << player.character;
            }

            else {
                cout << map[y][x];
            }

        }
        cout << endl;

    }

}

Personally, I would try and encapsulate the tiles behind a class. For instance (details missing for brevity):

struct Tile
{
    enum class Type { air, wallside, walltop, wallbottom, barrier, };
    Type type;
    bool collider;
};

class GameMap
{
private:
    std::map<char, Type> tiles_;
public:
    GameMap(std::vector<std::string> myMap)
    {
    // Probably sanity check that all strings are the same size, and record the length of that string
    // Maybe even validate the contents of the strings, so invalid characters throw an error.

       tiles_[' '] = Tile { Tile::Type::air, false };
       tiles_['#'] = Tile { Tile::Type::barrier, false };
       // ...
    } 

    Tile getTile(size_t xPos, size_t yPos)
    {
        if (xPos >= stringLength || yPos > myMap.size()
            throw runtime_error("Out of bounds");

        char tileMarker = myMap[yPos][xPos];

        auto tile = tiles.find(c);
        if (tile != tiles.end())
        {
            throw runtime_error("Invalid tile marker");
        }

        return *tile;
    }
};


// ...

std::vector<std::string> rawMapData = {
"###############################",
"#  [   ]                       ",
"#  [ _ ]                       ", 
"#              etc...          ", 
};

GameMap gameMap = GameMap(rawMapData);


Tile tile = gameMap.getTile(3, 5);
if (tile.collider)
{
    // ...
}

This way, you don't need to try and keep track of the state around the character as it's moving around, you can just query it as needed. ie. if the character tries to move left, you could say:

if (! gameMap.getTile(playerX - 1, playerY).collider)
{
     // Move the character
}

Edit: I see you still want an instance per tile, you can do a similar thing as above, but with a slight change:

class GameMap
{
private:
std::vector<std::vector<Tile>> tiles_;
public:
GameMap(std::vector<std::string> myMap)
{
    std::map<char, Tile> tileTypes;
    tileTypes[' '] = Tile { Tile::Type::air, false };
    tileTypes['#'] = Tile { Tile::Type::barrier, false };
    // ...

    for (const auto& row : myMap)
    {
        std::vector<Tile> tileRow;
        for (char c : row)
        {
            auto tile = tileTypes.find(c);
            if (tile != tileTypes.end())
            {
                throw runtime_error("Invalid tile marker");
            }

            tileRow.emplace_back(tile);
        }

        tiles_.emplace_back(std::move(tileRow));
    }
} 

Tile getTile(int x, int y)
{
    // return tile.  Return reference if it might change
}

I also wouldn't use map as a variable name, especially when you have using namespace std;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM