Package com.artemis.systems

Source Code of com.artemis.systems.DelayedEntityProcessingSystem

package com.artemis.systems;

import com.artemis.Aspect;
import com.artemis.Entity;
import com.artemis.EntitySystem;
import com.artemis.utils.Bag;
import com.artemis.utils.ImmutableBag;


/**
* The purpose of this class is to allow systems to execute at varying
* intervals.
* <p>
* An example system would be an ExpirationSystem, that deletes entities after
* a certain lifetime. Instead of running a system that decrements a timeLeft
* value for each entity, you can simply use this system to execute in a future
* at a time of the shortest lived entity, and then reset the system to run at
* a time in a future at a time of the shortest lived entity, etc.
* </p><p>
* Another example system would be an AnimationSystem. You know when you have
* to animate a certain entity, e.g. in 300 milliseconds. So you can set the
* system to run in 300 ms to perform the animation.
* </p><p>
* This will save CPU cycles in some scenarios.
* </p><p>
* Implementation notes:<br />
* In order to start the system you need to override the
* {@link #inserted(Entity) inserted(Entity e)} method, look up the delay time
* from that entity and offer it to the system by using the
* {@link #offerDelay(float) offerDelay(float delay)} method. Also, when
* processing the entities you must also call
* {@link #offerDelay(float) offerDelay(float delay)} for all valid entities.
* </p><p>
*
* @author Arni Arent
*/
public abstract class DelayedEntityProcessingSystem extends EntitySystem {

  /** The time until an entity should be processed. */
  private float delay;
  /**  If the system is running and counting down delays. */
  private boolean running;
  /** The countdown, accumulates world deltas. */
  private float acc;


  /**
   * Creates a new DelayedEntityProcessingSystem.
   *
   * @param aspect
   *      the aspect to match against entities
   */
  public DelayedEntityProcessingSystem(Aspect aspect) {
    super(aspect);
  }

  @Override
  protected final void processEntities(ImmutableBag<Entity> entities) {
    delay = Float.MAX_VALUE;
    Object[] array = ((Bag<Entity>)entities).getData();
    int processed = entities.size();
    for (int i = 0; processed > i; i++) {
      Entity entity = (Entity)array[i];
      processDelta(entity, acc);
      float remaining = getRemainingDelay(entity);
      if(remaining <= 0) {
        processExpired(entity);
      } else {
        offerDelay(remaining);
      }
    }
    acc = 0;
    if (getActives().size() == 0) stop();
  }


  @Override
  protected void inserted(Entity e) {
    float remainingDelay = getRemainingDelay(e);
    processDelta(e, -acc);
    if(remainingDelay > 0) {
      offerDelay(remainingDelay);
    }
  }
 
  /**
   * Return the delay until this entity should be processed.
   *
   * @param e
   *      entity
   *
   * @return delay
   */
  protected abstract float getRemainingDelay(Entity e);


  @Override
  protected final boolean checkProcessing() {
    if(running) {
      acc += getTimeDelta();
     
      if(acc >= delay) {
        return true;
      }
    }
    return false;
  }
 
  /**
   * Overridable method to provide custom time delta.
   */
  protected float getTimeDelta() {
    return world.getDelta();
  }
 
  /**
   * Process a entity this system is interested in.
   * <p>
   * Substract the accumulatedDelta from the entities defined delay.
   * </p>
   *
   * @param e
   *      the entity to process
   * @param accumulatedDelta
   *      the delta time since this system was last executed
   */
  protected abstract void processDelta(Entity e, float accumulatedDelta);


  protected abstract void processExpired(Entity e);

  /**
   * Start processing of entities after a certain amount of delta time.
   * <p>
   * Cancels current delayed run and starts a new one.
   * </p>
   *
   * @param delay
   *      time delay until processing starts
   * @deprecated bugged and unnecessary. don't use.
   */ @Deprecated
  public void restart(float delay) {
    this.delay = delay;
    this.acc = 0;
    running = true;
  }
 
  /**
   * Restarts the system only if the delay offered is shorter than the time
   * that the system is currently scheduled to execute at.
   * <p>
   * If the system is already stopped (not running) then the offered delay
   * will be used to restart the system with no matter its value.
   * </p><p>
   * If the system is already counting down, and the offered delay is  larger
   * than the time remaining, the system will ignore it. If the offered delay
   * is shorter than the time remaining, the system will restart itself to
   * run at the offered delay.
   * </p>
   *
   * @param offeredDelay
   *      delay to offer
   */
  public void offerDelay(float offeredDelay) {
    if (!running) {
      running = true;
      delay = offeredDelay;
    } else {
      delay = Math.min(delay, offeredDelay);
    }
  }
 
  /**
   * Get the initial delay that the system was ordered to process entities
   * after.
   *
   * @return the originally set delay
   */
  public float getInitialTimeDelay() {
    return delay;
  }
 
  /**
   * Get the time until the system is scheduled to run at.
   * <p>
   * Returns zero (0) if the system is not running.
   * Use {@link #isRunning() isRunning()} before checking this value.
   * </p>
   *
   * @return time when system will run at
   */
  public float getRemainingTimeUntilProcessing() {
    if(running) {
      return delay-acc;
    }
    return 0;
  }
 
  /**
   * Check if the system is counting down towards processing.
   *
   * @return {@code true} if it's counting down, false if it's not running
   */
  public boolean isRunning() {
    return running;
  }
 
  /**
   * Stops the system from running, aborts current countdown.
   * <p>
   * Call offerDelay or restart to run it again.
   * </p>
   */
  public void stop() {
    this.running = false;
    this.acc = 0;
  }

}
TOP

Related Classes of com.artemis.systems.DelayedEntityProcessingSystem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.