|
因此,在开发一个小游戏时,我发现通常用于碰撞检测的 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;
}
|
|