4

So i am writing a rpg java game and decided to use custom events to make the communication between two classes easier. At first i wrote an "enemyDeathEvent" to let the player know if an enemy died.

First i made my EnemyListener:

public interface EnemyListener {

    public void playerDeathEvent(EnemyEvent e);
}

After that i created the EnemyEvent class:

public class EnemyEvent {

    private Enemy enemy;

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

    public Enemy getSource() {
        return enemy;
    }
}

Then i set up the 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);
    }  
}

Lastly, in implemented the EnemyListener to the player:

public class Player implements EnemyListener {

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

So when the enemy dies the enemyDeathEvent() method from my player class will be called. everything works fine but my actual problem is that the game call this method more than once. the reason is that my update() method is connected to a thread which updates the game physics etc 30 times per second.

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

So my question is: How can i solve this problem so that my method will be called once?

I would appreciate every help! thanks

jww
  • 97,681
  • 90
  • 411
  • 885
AvarionDE
  • 160
  • 11
  • You seem to have an event driven program. Why do you have a multiple threads? I would recommend you to have a single thread (a timer) that updates the game 30 times per second. – aioobe Jun 08 '15 at 10:48

3 Answers3

1

You could update the dead field and fire the event only once, when the enemy dies:

public void update() {
    if(!dead && health <= 0) {
        dead = true;
        fireDeathEvent();
    }
}
tibtof
  • 7,857
  • 1
  • 32
  • 49
0

You need to stop updating your Enemy instance once it is dead.

Something like:

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

As a more general purpose solution, all your game instances should inherit from a base class (e.g. EntityBase). The base class can have a field named isEnabled and a basic update method:

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

All classes inheriting your EntityBase class must implements the updateImpl() method. Now to stop updating an instance, you just need to set the isEnabled flag to false.

void updateImpl() {
    if(health <= 0) {
        dead = true;
        isEnabled = false;
    }
    if(dead) fireDeathEvent();
}
Kryptos
  • 875
  • 8
  • 19
0

You need some special state for enemy that indicates killed state and check it in update method