LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 519|回复: 0

使用位操作进行碰撞检测

[复制链接]
发表于 2024-2-19 22:58:40 | 显示全部楼层 |阅读模式
因此,在开发一个小游戏时,我发现通常用于碰撞检测的 if 语句适用于单个方向,但是当我在多个方向上发生碰撞时,例如,在玩家面前检测到碰撞,但如果玩家右侧有可碰撞, 玩家将被允许向右移动到可碰撞中。我发现使用位操作可以非常有效地检测多个方向。下面不是我的游戏代码,而是我专门为展示这一点而制作的一个非常简洁的例子。我的问题是,在使用它进行碰撞检测时,这是否有任何缺点或我应该谨慎的任何事情?

#include <iostream>
#include <vector>
#include <string>
#include <memory>

enum class CollisionDirection
{
    IDLE = 0,
    UP = 1 << 0,
    DOWN = 1 << 1,
    LEFT = 1 << 2,
    RIGHT = 1 << 3
};

int CheckCollision(int& playerY, int& playerX, std::vector<std::vector<char>>& map, char collidable);

int main()
{
    const int mapWidth{ 10 };
    const int mapHeight{ 10 };
    const char mapTile{ '.' };

    const char player{ '*' };
    int playerY{ 2 };
    int playerX{ 2 };

    const char rock{ '&' };

    std::vector<std::vector<char>> map{ mapHeight, std::vector<char>(mapWidth, mapTile) };

    bool gameIsRunning{ true };

    int collisionFlags{};

    while (gameIsRunning)
    {
        map[playerY][playerX] = player;
        map[4][4] = rock;
        map[3][4] = rock;
        map[3][3] = rock;
        map[5][3] = rock;
        map[5][4] = rock;

        collisionFlags = CheckCollision(playerY, playerX, map, rock);

        for (const auto& col : map)
        {
            for (char row : col)
            {
                std::cout << row << ' ';
            }
            std::cout << '\n';
        }

        map[playerY][playerX] = mapTile;

        std::cout << "What direction would you like to go?\n\n";

        std::cout << "Debug - collisionFlags: " << collisionFlags << '\n';

        std::cout << "layer Y: " << playerY << " - Player X: " << playerX << "\n\n";

        std::cout << "W) Up\n";
        std::cout << "S) Down\n";
        std::cout << "A) Left\n";
        std::cout << "D) Right\n";

        char choice{ };

        std::cin >> choice;

        switch (choice)
        {
        case 'W':
        case 'w':
            if (!(collisionFlags & static_cast<int>(CollisionDirection::UP)) && playerY > 0)
            {
                --playerY;
            }
            break;

        case 'S':
        case 's':
            if (!(collisionFlags & static_cast<int>(CollisionDirection:OWN)) && playerY < mapHeight - 1)
            {
                ++playerY;
            }
            break;

        case 'A':
        case 'a':
            if (!(collisionFlags & static_cast<int>(CollisionDirection:EFT)) && playerX > 0)
            {
                --playerX;
            }
            break;

        case 'D':
        case 'd':
            if (!(collisionFlags & static_cast<int>(CollisionDirection::RIGHT)) && playerX < mapWidth - 1)
            {
                ++playerX;
            }
            break;
        }
    }
}

int CheckCollision(int& playerY, int& playerX, std::vector<std::vector<char>>& map, char collidable)
{
    int collision = static_cast<int>(CollisionDirection::IDLE);

    // Check collision above the player
    if (playerY > 0 && map[playerY - 1][playerX] == collidable)
    {
        collision |= static_cast<int>(CollisionDirection::UP);
    }

    // Check collision below the player
    if (playerY < map.size() - 1 && map[playerY + 1][playerX] == collidable)
    {
        collision |= static_cast<int>(CollisionDirection:OWN);
    }

    // Check collision to the left of the player
    if (playerX > 0 && map[playerY][playerX - 1] == collidable)
    {
        collision |= static_cast<int>(CollisionDirection:EFT);
    }

    // Check collision to the right of the player
    if (playerX < map[0].size() - 1 && map[playerY][playerX + 1] == collidable)
    {
        collision |= static_cast<int>(CollisionDirection::RIGHT);
    }

    return collision;
}

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表