C++控制台游戏碰撞检测失效问题求助
控制台汽车躲避游戏碰撞检测失效问题修复
我用C++结合Windows库开发了一款简易控制台汽车躲避障碍游戏,采用二维数组存储地图数据。原本碰撞检测逻辑是判断障碍物下方单元格是否被汽车占据,运行正常,但现在障碍物会直接穿过汽车,碰撞检测完全失效,修改代码后仍无法解决。
问题代码
#include <iostream> // for the text #include <cmath> #include <windows.h> // for the key press #include <stdlib.h> // for clearing console #define ROWS 16 #define COLUMNS 36 short SCORE = 0; short map[ROWS][COLUMNS]; bool GameOver = false; using namespace std; // Game classes class Car { public: short mapX = 6; short mapY = 10; void UpdateCar() { MoveCar(); } private: short direction = 0; // -1 is left, 1 is right short leftKey; short rightKey; void SetCar() { // car map[mapY][mapX] = 3; // origin map[mapY - 1][mapX] = 3; // top map[mapY + 1][mapX] = 3; // bottom map[mapY - 2][mapX] = 3; // top2 map[mapY + 2][mapX] = 3; // bottom2 map[mapY - 1][mapX - 1] = 3; // left map[mapY + 1][mapX - 1] = 3; // left2 map[mapY + 1][mapX + 1] = 3; // right map[mapY - 1][mapX + 1] = 3; // right2 } void EraseCar() { // car map[mapY][mapX] = 0; // origin map[mapY - 1][mapX] = 0; // top map[mapY + 1][mapX] = 0; // bottom map[mapY - 2][mapX] = 0; // top2 map[mapY + 2][mapX] = 0; // bottom2 map[mapY - 1][mapX - 1] = 0; // left map[mapY + 1][mapX - 1] = 0; // left2 map[mapY + 1][mapX + 1] = 0; // right map[mapY - 1][mapX + 1] = 0; // right2 } void MoveCar() { EraseCar(); // Key Checking leftKey = GetAsyncKeyState(VK_LEFT); rightKey = GetAsyncKeyState(VK_RIGHT); // Key setting the direction if (leftKey == 1) {direction = -1;} else if (rightKey == 1) {direction = 1;} // moving the car mapX += direction; // reset movement leftKey = 0; rightKey = 0; direction = 0; // setting car SetCar(); } }; class Obstacle { public: short mapX = 5; short mapY = 1; void UpdateObstacle() { if (CollideWithCar() == false) { EraseObstacle(); ChangeX(); mapY++; // move the obstacle down 1 grid cell DrawObstacle(); } else { GameOver = true; } } private: bool OnEdge() { if (mapY == ROWS - 1) { // is obstacle on the bottom return true; // return true } return false; } void ChangeX() { // set the obstacle X to a random number from 1 - COLUMNS - 1 if (OnEdge()) { mapX = (int)(rand() % (COLUMNS - 2)) + 2; mapY = 1; SCORE++; // increase the score } } void DrawObstacle() { map[mapY][mapX] = 4; map[mapY][mapX + 1] = 4; } void EraseObstacle() { map[mapY][mapX] = 0; map[mapY][mapX + 1] = 0; } bool CollideWithCar() { if (map[mapY+1][mapX] == 3 || map[mapY+1][mapX+1] == 3) { return true; } return false; } }; class Game { public: Car c; Obstacle o; // Map functions void DrawMap() { for (int y = 0; y < ROWS; y++) { for (int x = 0; x < COLUMNS; x++) { switch(map[y][x]) { case 0: cout << " "; // empty break; case 1: cout << "[]"; // wall break; case 2: cout << "||"; // road break; case 3: cout << "()"; // car break; case 4: cout << "{}"; // obstacle break; } } // Make a new lines after the end of each column cout << "" << endl; } } // Defining the Game void DefineMap() { for (int y = 0; y < ROWS; y++) { for (int x = 0; x < COLUMNS; x++) { // Define the border if (x == 0 || x == COLUMNS - 1 || y == 0 || y == ROWS - 1) { map[y][x] = 1; } else {map[y][x] = 0;} } } } void DefineRoad() { for (int y = 0; y < ROWS; y++) { for (int x = (COLUMNS / 2) - 1; x < (COLUMNS / 2); x++) { map[y][x] = 2; // 2 is road } } } void DefineGame() { DefineRoad(); DefineMap(); } Game() { // constructor DefineGame(); } // restarting the game void RestartGame() { o.mapY = 1; c.mapX = 6; c.mapY = 10; } // Updating the game void UpdateGame() { DefineMap(); // define the map DefineRoad(); // define the road o.UpdateObstacle(); // update the obstacle c.UpdateCar(); // update the car DrawMap(); // draw the map } }; void GameOverText() { // too long to add not useful } int main() { // escape key short escape = GetAsyncKeyState(VK_UP); // restart short restart = GetAsyncKeyState(VK_SPACE); // Game object Game g; // game loop while (escape == 0) { escape = GetAsyncKeyState(VK_UP); // check for the escape key // Game logic if (GameOver == false) { Sleep(500); // sleep for half a second then update the screen system("cls"); // clear the screen // DEBUGGING for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLUMNS; j++) { cout << map[i][j]; } cout << "" << endl; } g.UpdateGame(); // update the game cout << "SCORE: " << SCORE << " " << "LEFT AND RIGHT ARROWS TO MOVE" << endl; // draw the score cout << "SPACE IS FOR RESTART" << endl; // draw the score cout << "ESCAPE IS FOR LEAVING" << endl; // draw the score } else { Sleep(1000); // sleep for a second then update the screen system("cls"); // clear the screen GameOverText(); // do the game over restart = GetAsyncKeyState(VK_SPACE); // get restart key if (restart == 1) {GameOver = false; g.RestartGame();} // if key is pressed } } // ending system("cls"); cout << "THANKS FOR PLAYING"; }
问题分析
- 更新顺序错误:
UpdateGame()先处理障碍物再绘制汽车,而DefineMap()已将地图重置为初始状态,碰撞检测时地图上还没有汽车的标记3,导致检测失效。 - 碰撞时机错误:
UpdateObstacle()先检测碰撞再移动障碍物,且检测的是障碍物下方位置,此时障碍物未移动,加上地图已重置,逻辑完全无效。 - 按键检测逻辑错误:用
GetAsyncKeyState() == 1判断按键,只会在按键刚按下瞬间生效,导致汽车移动不灵敏。
修复方案
1. 调整游戏更新顺序
修改Game类的UpdateGame()方法,先绘制汽车再处理障碍物:
void UpdateGame() { DefineMap(); // 重置地图 DefineRoad(); // 绘制道路 c.UpdateCar(); // 先将汽车绘制到地图 o.UpdateObstacle(); // 再处理障碍物,确保碰撞检测能识别汽车 DrawMap(); // 绘制最终地图 }
2. 重构障碍物更新与碰撞检测
修改Obstacle类的UpdateObstacle()方法,提前检查障碍物下一个位置是否与汽车重叠:
void UpdateObstacle() { EraseObstacle(); // 擦除当前位置障碍物 ChangeX(); // 到达边界则重置位置 short nextY = mapY + 1; // 检查下一个位置是否与汽车碰撞 if (map[nextY][mapX] == 3 || map[nextY][mapX+1] == 3) { GameOver = true; DrawObstacle(); return; } mapY = nextY; DrawObstacle(); // 绘制新位置的障碍物 }
3. 修复按键检测逻辑
修改Car类的MoveCar()方法,正确判断按键持续按下状态,并增加边界限制:
void MoveCar() { EraseCar(); bool leftPressed = (GetAsyncKeyState(VK_LEFT) & 0x8000) != 0; bool rightPressed = (GetAsyncKeyState(VK_RIGHT) & 0x8000) != 0; if (leftPressed) {direction = -1;} else if (rightPressed) {direction = 1;} // 限制汽车移动范围,防止移出道路 if (mapX + direction >= 2 && mapX + direction <= COLUMNS - 3) { mapX += direction; } direction = 0; SetCar(); }
4. 调整障碍物边界判断
修改Obstacle类的OnEdge()方法,避免障碍物移动到底部边框:
bool OnEdge() { if (mapY >= ROWS - 2) { // 到达倒数第二行即视为边界 return true; } return false; }
内容的提问来源于stack exchange,提问作者ripe_onions
相关产品推荐
相关产品推荐

