How to wait for X seconds to add an object in an arrayList?

1

I'm trying to make a mini game where the enemies spawn around the player, the problem is that they come out very fast and very often and the gameplay is very difficult, these enemies are part of an arrayList of "enemy" objects and I wanted to know if there is any method that allows me to slow down its appearance. It is clear that I try to do it in the following way:

Class RunAction:

public class EjecutarAccion implements Runnable{

boolean detenerEjecucion = false;

public void detenerEjecucion(boolean decision){
    this.detenerEjecucion = decision;
}

@Override
public void run() {
    while(!detenerEjecucion){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            Logger.getLogger(EjecutarAccion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

}

Drawing class - Paint method:

Thread hilo = new Thread(ejecutar);

 public void paint(Graphics g) {
    add(jugador);
    super.paintComponent(g);
    setBackground(Color.BLACK);
    jugador.dibujarJugador(g);
    jugador.disparar(g, bala);
    hilo.start();
    if (enemigos.size() <= 1) {
        enemigos.add(new Enemigo());
    }
}

As you can see my intention is to wait 5 seconds between the spawneo of each enemy. The problem of doing it this way is that I pause the whole game 5 seconds every time I destroy an enemy and go to spawnear another; that's why I wanted to know if there is a way to do this without affecting the whole game.

    
asked by Smuk 18.08.2017 в 22:41
source

2 answers

1

How about a java.util.Timer ?

new Timer().schedule(new TimerTask() {
    @Override
    public void run() {
        enemigos.add(new Enemigo());
    }
}, 5000); //espera 5 segundos para a~adir un enemigo

NOTE: If you put a Timer in paint, just checking the size of the enemy's array will result in a creation of an% nu Timers until the 5 seconds are met and the enemigos.size is greater or same as 2

I'm sure you can find a better place to put this Timer or add some more conditions to that if like for example:

if(enemigos.size() <= 1 && !estaAnadiendoEnemigo ){
    estaAnadiendoEnemigo = true;
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            enemigos.add(new Enemigo());
            estaAnadiendoEnemigo = false;
        }
    }, 5000); //espera 5 segundos para a~adir un enemigo
}

EDIT:

If you want to add a specific number of enemies when enemigos.size is < = 1, example:

  

the player eliminated an enemy and now only 1 remains, the program has   than create 10 more enemies in a 5-second interval

if(enemigos.size() <= 1 && !estaAnadiendoEnemigo ){
    estaAnadiendoEnemigo = true;
    new Timer().schedule(new TimerTask() {
        int contador = 0;
        @Override
        public void run() {                
            enemigos.add(new Enemigo());
            contador++;
            if(contador == 10){ 
                estaAnadiendoEnemigo = false; // terminó de añadir 10 enemigos
                cancel(); // cancelar el task para que no siga ejecutando
            }
        }
    }, 5000, 5000); //Nota que ahora hay dos números, tiempoAesperarParaEjecutar y intervaloEntreEjecuciones
}
    
answered by 19.08.2017 / 04:49
source
0

You can create a class that extends from Runnable and pass as a parameter the function you want to execute or create it within this class. Then you create a new thread and pass it an instance of the class to run it in "parallel".

 public class EjecutarAccion implements Runnable {
 boolean detenerEje = false;

Thread hilo;

 public void detenerEjecucion(boolean a){
      this.detenerEje = a;
 }

  public void setHilo(Thread hilo) {
    this.hilo = hilo;
  }



 @Override
 public void run() {
    while (!detenerEje){
        System.out.println("accion!!!");
        try {
            this.hilo.sleep(5000);
        } catch (InterruptedException ex) {
            Logger.getLogger(EjecutarAccion .class.getName())
            .log(Level.SEVERE, null, ex);
        }
     }
   }
}

This class will run every 5000 milliseconds and start it as:

EjecutarAccion accionFoo = new EjecutarAccion();

Thread hilo = new Thread(accionFoo);
accionFoo.setHilo(accionFoo);  
hilo.start();

Then you stop with accionFoo.detenerEjecucion(true); because hilo.stop() is insecure according to the documentation. This way lets the process die on its own.

Sorry if the code is something wrong, I shot it directly in the forum. Anything I check it but already in my house.

UPDATE

Over there they corrected me very nicely. Actually if the screen froze because it was calling directly Thread.sleep which is the main thread of the program and therefore freezes. To avoid that, I pass as an instance the new thread that was created and I save it in a variable inside the class EjecutarAccion . Then I do this.hilo.sleep(5000) and the main thread does not stop.

CLARIFICATION

This part occupies initiate it in this way:

public void paint(Graphics g) {
        add(jugador);
        super.paintComponent(g);
        setBackground(Color.BLACK);
        jugador.dibujarJugador(g);
        jugador.disparar(g, bala);
        if (!hilo.isAlive()) {
            ejecutar.setArregloEnemigos(enemigos);
            hilo.start();

        }

    }

And within the method run() of the class EjecutarAccion you pass with a set the array enemigos and you will make it grow from there in this way:

@Override
   public void run() {
        while (!detenerEje){
            if (enemigos.size() <= 1) {
                 enemigos.add(new Enemigo());
            }
            try {
                this.hilo.sleep(5000);
            } catch (InterruptedException ex) {
                Logger.getLogger(EjecutarAccion .class.getName())
                .log(Level.SEVERE, null, ex);
            }
        }
   } 
    
answered by 19.08.2017 в 00:54