Creating a timer trigger

In the Creating a trigger system recipe, we laid the foundation for a Trigger system as well as created some basic implementations. A timer can be very useful when creating complex scripts that rely on timing or sequenced events. Not only does it do the obvious (trigger the blast of the door and then the soldiers running through) but it can also work as a relay trigger in case many things should be triggered at the same time. In this recipe, we'll create this Timer object as well as an actual implementation of it where it triggers an explosion with several components. To save some time, we'll use the TestExplosion test from jMonkeyEngine to get ParticleEmitters set up and the timing for free. We'll also create a new ScriptObject called PlayEffect, which controls the particle emitters.

How to do it...

To be able to control a ParticleEmitter object from our script system, we need a new class to handle the ParticleEmitter object:

  1. Start by creating a new class called PlayEffect, which implements ScriptObject.
  2. The PlayEffect class needs a Boolean called emitAllParticles, a ParticleEmitter field called effect, and a Boolean to control whether it's enabled or not (default it to true).
  3. The trigger method should call onTrigger if the object is enabled.
  4. The onTrigger method should enable effect and if emitAllParticles is true, it should call emitter.emitAllParticles().

Apart from the setter methods, this is all that's needed for the PlayEffect class. Now, we can look at the Timer class by performing the following steps:

  1. We create a new class called Timer, which implements ScriptObject.
  2. It will use a simple callback interface to keep track of events:
    public interface TimerEvent{
      public Object[] call();
    }
  3. It needs two Boolean fields. One called enabled and another called running. It also needs to keep track of time with three floats called time, lastTime, and maxTime.
  4. Finally, we will store the events in HashMap<Float, TimerEvent>.
  5. We need a method to add events to the timer. Call it addTimerEvent and add inputs for time in seconds to execute the event, as well as a TimerEvent object with the code to execute it. After TimerEvent is placed in the timerEvents map, we check whether the supplied time value is higher than the current maxTime and set maxTime to time if true, as shown in the following code:
    public void addTimerEvent(float time, TimerEvent callback){
      timerEvents.put(time, callback);
      if(time >maxTime ){
        maxTime = time;
      }
    }
  6. The trigger method should call onTrigger, if it is enabled.
  7. The onTrigger method should set time to 0 and set running to true.
  8. The update method should first check whether the Timer is enabled and running.
  9. If it is, tpf should be added to the time.
  10. Inside the same statement, we then create an iterator based on keySet of timerEvents and parse through it. If the key (a float) is more than lastTime and less or equal to the current time, we should get the corresponding value from the timerEvents map and execute it. Otherwise, if the key is less than lastTime, we should just continue using the following code:
    Iterator<Float> it = timerEvents.keySet().iterator();
    while(it.hasNext()){
      float t = it.next();
      if(t >lastTime&& t <= time){
        TimerEvent event = timerEvents.get(t);
        if(event != null){
          event.call();
        }
      } else if(t <lastTime){
        continue;
      }
    }
  11. Outside of the previous loop, we check if time is more than maxTime, in which case, we should set running to false.
  12. Finally in the update method, we set lastTime to be equal to time.

With the basic logic done, let's take a look at how we can use the timer for something real and use it to trigger an explosion by performing the following steps:

  1. Copy the TestExplosion class from jMonkeyEngine's test package and strip it from everything except the methods that create ParticleEmitters and the lines in simpleInitApp, which uses them and sets up the camera.
  2. Then, create a PlayEffect instance for each of ParticleEmitters and set the effect accordingly with emitAllParticles set to true.
  3. Create a new Timer instance called explosionTimer.
  4. Add a new TimerEvent at time 0 where it triggers the flash, spark, smoke, debris, and shockwave effects, by calling trigger() on each of the PlayEffects, as shown in the following code:
    explosionTimer.addTimerEvent(0, new Timer.TimerEvent() {
    
      public Object[] call() {
        flashEffect.trigger();
        sparkEffect.trigger();
        ...
        return null;
      }
    });
  5. Then, add another TimerEvent at time 0.05f, which triggers the flame and roundSpark effects.
  6. The last TimerEvent should happen at time 5f and should call stop() on all of the effects.
  7. Finally, we create a ScriptAppState instance to which we add explosionTimer and then add it to stateManager using the following code:
    ScriptAppStateappState = new ScriptAppState();
    stateManager.attach(appState);
    appState.addScriptObject(explosionTimer);
  8. Now, we can trigger explosionTimer. It should perform the explosion in the same way as TestExplosion does.

How it works...

Once triggered, Timer works by checking the time that has passed since it was started (time). It then checks each of the events in the timerEvents map to see whether their execution time is anywhere between the current time and the last time (lastTime). The maxTime option is used by the Timer to know when it has executed the last of its events and can switch itself off. If the Timer was only meant to be used once, the events can simply be removed from the timerEvent map. This way it can be reused.

The PlayEffect instance has a fairly simple functionality to turn it on and off. Since ParticleEmitters can be used in two ways, fire all their particles at once, or emit a continuous stream of particles, it needs to know which way to fire it.

In the example application, we create ScriptAppState since it's needed to update the Timer with the passed time. We don't need to add the PlayEffect instances since they don't use the update method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.156.235