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

基于关卡从LinkedList移除对象时触发NullPointerException问题求助

解决你的空指针问题与Boss生成逻辑优化

看起来你遇到的NullPointerException根源非常清晰——你的BasicEnemy类中的hud引用没有被正确初始化,导致在执行if(hud.level % 10 == 0)这行代码时,无法访问hud对象的level属性。我们一步步来解决这个问题,同时优化你的敌人移除和Boss生成逻辑:


核心问题:HUD引用未初始化

你在BasicEnemy的tick方法里直接访问hud.level,但如果没有在BasicEnemy的构造过程中传入并保存当前的HUD实例,这个hud变量就会是null,触发空指针异常。

修复步骤:

  1. 修改BasicEnemy类,添加HUD成员变量并在构造函数中初始化:
public class BasicEnemy extends GameObject {
    private HUD hud; // 添加HUD成员变量

    // 修改构造函数,传入HUD实例
    public BasicEnemy(float x, float y, ID id, HUD hud) {
        super(x, y, id);
        this.hud = hud; // 初始化hud引用
    }

    // 你的tick方法
    public void tick() {
        // 增加空判断,避免极端情况下的空指针
        if(hud != null && hud.level % 10 == 0) {
            this.removed = true;
        }
        // 其他逻辑...
    }
}
  1. 生成BasicEnemy时传入当前的HUD实例:
    确保你在创建BasicEnemy对象的地方(比如游戏的敌人生成逻辑里),把当前的HUD对象传进去,例如:
// 假设你有一个当前的hud实例
HUD gameHud = new HUD();
handler.addObject(new BasicEnemy(100, 100, ID.BasicEnemy, gameHud));

优化LinkedList的元素移除逻辑

你当前的移除逻辑存在一个隐藏问题:使用索引遍历LinkedList并删除元素时,会导致后续元素前移,从而跳过下一个元素的检查。比如删除索引i的元素后,原来的i+1元素会移到i的位置,但你的循环i++会直接跳过它。

推荐的两种修复方式:

方式1:使用迭代器遍历(LinkedList的最优遍历删除方式)

// 在Handler类中
Iterator<GameObject> iterator = object.iterator();
while(iterator.hasNext()) {
    GameObject obj = iterator.next();
    if(obj.removed) {
        iterator.remove(); // 用迭代器的remove方法安全删除
    }
}

方式2:从后往前遍历索引

// 在Handler类中
for(int i = object.size() - 1; i >= 0; i--) {
    GameObject obj = object.get(i);
    if(obj.removed) {
        object.remove(i);
    }
}

完善Boss生成与敌人清除的触发逻辑

你当前的逻辑是每帧都检查关卡并标记敌人为移除,这可能导致重复操作。建议改为当关卡提升到10的倍数时,一次性触发敌人清除和Boss生成,避免每帧执行判断:

示例实现(在HUD的关卡提升逻辑中扩展):

// HUD类的tick方法修改
public void tick() {
    HEALTH = Game.clamp(HEALTH, 0, 100);
    greenValue = Game.clamp(greenValue, 0, 255);
    greenValue = HEALTH * 2;
    score++;

    scoreKeep ++;
    if(scoreKeep >= 100) {
        scoreKeep = 0;
        int oldLevel = this.getLevel();
        this.setLevel(oldLevel + 1);
        int newLevel = oldLevel + 1;
        
        // 当新关卡是10的倍数时,触发清除和Boss生成
        if(newLevel % 10 == 0) {
            // 调用Handler的方法清除所有非Boss敌人
            handler.clearNonBossEnemies();
            // 生成Boss(假设BossEnemy是你的Boss类)
            handler.addObject(new BossEnemy(Game.WIDTH/2 - 50, Game.HEIGHT/2 - 50, ID.Boss, this));
        }
    }
}

// 在Handler类中添加clearNonBossEnemies方法
public void clearNonBossEnemies() {
    Iterator<GameObject> iterator = object.iterator();
    while(iterator.hasNext()) {
        GameObject obj = iterator.next();
        if(obj.getId() != ID.Boss) { // 假设Boss的ID是ID.Boss
            iterator.remove();
        }
    }
}

这样可以确保只有在关卡真正提升到10的倍数时才执行一次清除和Boss生成,而不是每帧都标记敌人移除,逻辑更高效清晰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:22:17