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()方法里:
- 绘制玩家之后,添加绘制敌人的循环:
// 绘制敌人 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 ); } }
- 在所有绘制完成后,把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
相关产品推荐
相关产品推荐

