如何使用在 C++ 中定义地图的 2d 数组在 cmd 中为我的冒险游戏添加碰撞器?

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

我目前正在编写 2d cmd 冒险游戏的起始结构。如果您查看提供的代码,我将我的图块存储在一个结构中,并且我有一个用于对撞机的布尔值。

我最初的想法是在角色周围有4个'nodes'并且在下面的移动命令中会有一个if语句检查节点的位置并查看是否有碰撞器瓦片看看你是否可以搬到那里或不。

我卡住了,因为我将图块存储为字符 "barrier.type",我只想读取 "barrier.type" 而不是当前存储在其中的字符数据“#”。我想到这样做的唯一方法是将位置设为字符串,然后删除它的最后 4 个字母并添加对撞机,但我不知道这将如何工作,因为它们是两种不同的数据类型,除非我能以某种方式获得char 到一个字符串。在那种情况下,我想如果我把它变成一个字符串,它会使“#”成为一个字符串。

如果有人对检查碰撞器或如何实现我的原始想法有更好的想法,我当前的播放器和瓷砖系统非常灵活,我愿意接受各种细节。

代码:

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;

    }

}

就个人而言,我会尝试将图块封装在 class 后面。例如(为简洁起见缺少详细信息):

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)
{
    // ...
}

这样,您无需在角色四处移动时尝试跟踪角色周围的状态,您可以根据需要查询它。 IE。如果角色试图向左移动,你可以说:

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

编辑:我看到您仍然想要每个图块一个实例,您可以执行与上述类似的操作,但稍作更改:

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
}

我也不会使用 map 作为变量名,尤其是当你有 using namespace std;