调用一次自定义事件(游戏开发)

Call custom Event once (Game Development)

所以我正在编写一个 rpg java 游戏,并决定使用自定义事件来使两个 classes 之间的通信更容易。起初我写了一个 "enemyDeathEvent" 让玩家知道敌人是否死亡。

首先我做了我的 EnemyListener:

public interface EnemyListener {

    public void playerDeathEvent(EnemyEvent e);
}

之后我创建了 EnemyEvent class:

public class EnemyEvent {

    private Enemy enemy;

    public EnemyEvent(Enemy enemy) {
        this.enemy = enemy;
    }

    public Enemy getSource() {
        return enemy;
    }
}

然后我设置敌人class:

public class Enemy {

    //......
    private boolean dead;

    private Set<EnemyListener> listeners;

    public Enemy() {
        listeners = new HashSet<EnemyListener>();
    }

    //checks if the enemy is dead
    public void update() {
        if(health <= 0) dead = true;

        if(dead) fireDeathEvent();
    }

    //fires the death event
    protecd synchronized void fireDeathEvent() {
        EnemyEvent e = new EnemyEvent(this);
        for(EnemyListener listener : listeners) {
            listeners.enemyDeathEvent(e);
        }
    }

    public void addEnemyListener(EnemyListener listener) {
        listeners.add(listener);
    }  
}

最后,为玩家实现了 EnemyListener:

public class Player implements EnemyListener {

    @Override
    public void enemyDeathEvent(EnemyEvent e) {
        System.out.println(e.getSource().getName() + " died!");
    }
}

所以当敌人死亡时,我的玩家 class 的 enemyDeathEvent() 方法将被调用。一切正常但我的实际问题是游戏不止一次调用此方法。原因是我的 update() 方法连接到每秒更新游戏物理等 30 次的线程。

@Override
public void run() {
    while(gameRunning) {
        update();
        render();
        try {
            Thread.sleep(1000/30);  //30FPS
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

所以我的问题是:如何解决这个问题,以便我的方法被调用一次?

我将不胜感激!谢谢

您需要在 Enemy 实例失效后停止更新它。

类似于:

void update() {
    if (dead) return;
    ...
}

作为更通用的解决方案,您的所有游戏实例都应继承自基础 class(例如 EntityBase)。基础 class 可以有一个名为 isEnabled 的字段和一个基本的更新方法:

void update() {
    if (!isEnabled) return;
    updateImpl();
}
abstract void updateImpl();

所有继承您的 EntityBase class 的 classes 必须实现 updateImpl() 方法。现在要停止更新实例,只需将 isEnabled 标志设置为 false.

void updateImpl() {
    if(health <= 0) {
        dead = true;
        isEnabled = false;
    }
    if(dead) fireDeathEvent();
}

您可以更新 dead 字段并仅在敌人死亡时触发一次事件:

public void update() {
    if(!dead && health <= 0) {
        dead = true;
        fireDeathEvent();
    }
}

你需要一些特殊的敌人状态来指示被杀死的状态,并在更新方法中检查它