【问题标题】:Call custom Event once (Game Development)调用自定义事件一次(游戏开发)
【发布时间】:2015-06-08 10:45:14
【问题描述】:

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

首先我创建了我的 EnemyListener:

public interface EnemyListener {

    public void playerDeathEvent(EnemyEvent e);
}

之后我创建了 EnemyEvent 类:

public class EnemyEvent {

    private Enemy enemy;

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

    public Enemy getSource() {
        return enemy;
    }
}

然后我设置 Enemy 类:

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!");
    }
}

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

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

所以我的问题是:我怎样才能解决这个问题,以便我的方法会被调用一次?

我将不胜感激!谢谢

【问题讨论】:

  • 您似乎有一个事件驱动程序。为什么你有多个线程?我建议您使用一个线程(计时器)每秒更新游戏 30 次。

标签: java custom-events


【解决方案1】:

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

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

【讨论】:

  • 或者一个布尔类变量来表明它是否已经触发了事件?
【解决方案2】:

您需要在 Enemy 实例死亡后停止更新它。

类似:

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      相关资源
      最近更新 更多