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

Enemy类无法向Goal类移动问题求助(附GameManager代码)

敌人无法向目标移动的排查方案

嘿,我来帮你找出敌人不移动的问题!结合你给出的GameManager代码,咱们从几个关键方向入手排查:


1. Enemy类的performAction()方法逻辑是否正确

你提到已经在Enemy类里实现了移动逻辑,但目前没看到这部分代码,这是最核心的环节。要确保:

  • Enemy能通过传入的GameManager正确获取到Goal对象的坐标(比如GameManager要有public Goal getGoal() { return goal; }这样的方法)
  • 移动逻辑正确计算了朝向Goal的方向,并且更新了自身的X/Y坐标
  • 移动速度设置合理(你也提到要远小于玩家,比如设为1或2)

举个正确的移动逻辑示例:

public class Enemy {
    private GameManager gameManager;
    private int x, y;
    private boolean isAlive;
    private static final int ENEMY_SPEED = 1; // 远小于玩家速度

    public Enemy(GameManager gameManager, int startX, int startY) {
        this.gameManager = gameManager;
        this.x = startX;
        this.y = startY;
        this.isAlive = true;
    }

    public void performAction() {
        if (!isAlive) return; // 死亡状态不移动

        Goal goal = gameManager.getGoal();
        if (goal == null || !goal.isAlive()) return; // 目标已死亡也不用移动

        // 计算朝向目标的方向
        int dx = goal.getX() - this.x;
        int dy = goal.getY() - this.y;
        double distance = Math.sqrt(dx * dx + dy * dy);

        if (distance > 0) { // 避免除以0(和目标重合时不移动)
            // 归一化方向后乘以速度,更新坐标
            this.x += (int) ((dx / distance) * ENEMY_SPEED);
            this.y += (int) ((dy / distance) * ENEMY_SPEED);
        }
    }

    // 别忘了getter和setter
    public int getX() { return x; }
    public int getY() { return y; }
    public boolean isAlive() { return isAlive; }
    public void die() { this.isAlive = false; }
}

2. 敌人的坐标更新后没有被正确绘制

看你给出的GameManager代码,绘制敌人的部分被截断了,而且最后也没有把canvas的内容绘制到窗口上!这会导致就算敌人坐标更新了,屏幕上也看不到变化。

你需要在updateCanvas()方法里:

  1. 绘制玩家之后,添加绘制敌人的循环:
// 绘制敌人
for (int i = 0; i < this.numEnemies; i++) {
    Enemy enemy = this.enemies[i];
    if (enemy.isAlive()) {
        canvasGraphics.drawImage(
            enemy.getCurrentImage(),
            enemy.getX() - (enemy.getCurrentImage().getWidth() / 2),
            enemy.getY() - (enemy.getCurrentImage().getHeight() / 2),
            null
        );
    }
}
  1. 在所有绘制完成后,把canvas绘制到窗口的Graphics上:
// 将canvas内容绘制到窗口
gameGraphics.drawImage(canvas, borderLeft, borderTop, null);

3. 游戏循环阻塞了UI线程

你现在把游戏循环放在GameManager的构造函数里,用while(this.continueGame)直接执行,这会阻塞Swing的事件调度线程(EDT),导致UI完全无法刷新,就算敌人坐标变了,屏幕也不会更新。

解决办法是使用javax.swing.Timer来实现游戏循环,让UI线程负责绘制,定时器触发逻辑更新:

// 替换构造函数里的while循环
Timer gameTimer = new Timer(16, e -> { // 约60帧每秒
    if (continueGame) {
        updateCanvas();
    } else {
        ((Timer)e.getSource()).stop();
        stage.setGameOverBackground();
        updateCanvas();
    }
});
gameTimer.start();

4. 敌人的存活状态是否正确

要确认Enemy对象初始化后isAlive()返回true,如果不小心在创建后调用了die(),或者初始状态设为false,performAction()里的移动逻辑就不会执行。

你可以在GameManager创建敌人后加个日志或者打印,确认敌人的存活状态:

for (int i = 0; i < this.numEnemies; i++) {
    this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth / 4), Math.abs(rng.nextInt()) % this.canvasHeight);
    System.out.println("Enemy " + i + " alive: " + this.enemies[i].isAlive());
}

内容的提问来源于stack exchange,提问作者sogyals429

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:24:57