文本像素坦克射击游戏:射击后玩家无法移动问题修复咨询
修复:发射子弹后玩家无法移动的问题
问题根源
你的代码中,Bullet类的构造函数直接调用了move方法,而move方法内部有一个无限while循环——这个循环会一直执行直到子弹移出屏幕,完全阻塞了主线程的输入处理和玩家移动逻辑。主线程被卡在子弹的移动循环里,根本没法处理后续的按键输入,所以玩家动不了。
修复步骤及代码修改
1. 重构Bullet类,移除阻塞式循环
把move方法改成单次移动逻辑,每次只移动子弹一步,返回布尔值表示子弹是否还存活(未移出屏幕):
// Game Objects.h - 修改Bullet类 class Bullet { private: std::string bullet = "\xDF"; Transform transform; public: Bullet(int x, int y) { transform.x = x; transform.y = y; screen.create_object(bullet, transform.x, transform.y); } // 返回true表示子弹存活,false表示已移出屏幕需销毁 bool move(int direction) { switch (direction) { case left: if (transform.x - 1 < 3) { screen.clear_object(bullet, transform.x, transform.y); return false; } screen.clear_object(bullet, transform.x, transform.y); transform.x--; screen.create_object(bullet, transform.x, transform.y); return true; default: return true; } } };
2. 让玩家类维护子弹列表
在MainPlayer中添加子弹列表,shoot方法创建子弹并加入列表,同时提供获取列表的接口供主循环更新:
// Game Objects.h - 修改MainPlayer类,先添加头文件 #include <vector> class MainPlayer { private: std::string Player = " \xDC \xDC \xDC \xDC \xDC \xDC\n \xDB\xDF\xDF\xDF\xDF\xDF\xDF\xDF\xDB \n \xDC\xDB\xDC\xDC\xDC\xDC\xDC \xDB \n\xDF\xDF\xDB\xDB\xDB\xDB\xDB\xDC\xDB \xDB \n \xDB \xDB \n \xDC\xDF\xDB\xDF\xDB\xDF\xDB\xDF\xDB\xDF\xDC"; Transform transform; std::vector<Bullet*> bullets; // 存储所有活跃子弹 public: MainPlayer(int x, int y) { transform.x = x; transform.y = y; screen.create_object(Player, transform.x, transform.y); } ~MainPlayer() { // 清理子弹内存 for (auto bullet : bullets) { delete bullet; } bullets.clear(); } void move(int direction) { int x = transform.x; int y = transform.y; switch (direction) { case up: // 修正边界判断逻辑,原y--会导致判断错误 if (y - 1 < 2) return; screen.clear_object(Player, transform.x, transform.y); transform.y--; screen.create_object(Player, transform.x, transform.y); break; case down: if (y + 1 > 35) return; screen.clear_object(Player, transform.x, transform.y); transform.y++; screen.create_object(Player, transform.x, transform.y); break; case left: break; case right: break; } } void shoot() { bullets.push_back(new Bullet(transform.x - 1, transform.y + 3)); } // 供主循环获取子弹列表 std::vector<Bullet*>& getBullets() { return bullets; } };
3. 修改主循环,统一更新所有元素
主循环每次迭代同时处理输入、玩家移动和子弹更新,确保所有逻辑并行推进:
// Game Land.cpp - 修改主循环 #include "Controls.h" #include "Game Objects.h" #include <vector> Border border(0, 0); MainPlayer Player(102, 18); int main() { while (true) { input.refresh(); // 处理玩家移动输入 if (input.get().up) Player.move(up); if (input.get().down) Player.move(down); if (input.get().space) { Player.shoot(); } // 更新所有子弹,移除已消失的子弹 auto& bullets = Player.getBullets(); for (auto it = bullets.begin(); it != bullets.end(); ) { if (!(*it)->move(left)) { delete *it; it = bullets.erase(it); } else { ++it; } } // 统一控制帧率,避免CPU占用过高 Sleep(8); } }
核心逻辑说明
- 把子弹的持续移动从阻塞式循环改成逐帧更新,让主循环始终掌握控制权,能同时处理输入和所有游戏元素。
- 用
vector管理子弹生命周期,主循环负责更新和清理,避免内存泄漏。 - 修正了玩家移动的边界判断错误,防止玩家移出边界的逻辑失效。
内容的提问来源于stack exchange,提问作者Sam Kivin Heiden
相关产品推荐
相关产品推荐

