You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

文本像素坦克射击游戏:射击后玩家无法移动问题修复咨询

修复:发射子弹后玩家无法移动的问题

问题根源

你的代码中,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:09:57