All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artemis.systems.DelayedIteratingSystem Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
package com.artemis.systems;

import com.artemis.*;
import com.artemis.utils.IntBag;

/**
 * Tracks cooldown per entity, processing entity when its timer runs out.
 * 

* 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. *

* 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. *

* This will save CPU cycles in some scenarios. *

* Implementation notes:
* Within {@link #processExpired(int) processExpired(Entity e)} * you must call {@link #offerDelay(float) offerDelay(float delay)} if the * entity's delay time is renewed. That method is also called by {@link #inserted(int) inserted(int entityId)} * for each newly matched entity. *

* * @author Arni Arent */ public abstract class DelayedIteratingSystem extends BaseEntitySystem { /** 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 DelayedIteratingSystem(Aspect.Builder aspect) { super(aspect); } @Override protected final void processSystem() { IntBag entities = subscription.getEntities(); int processed = entities.size(); if (processed == 0) { stop(); return; } delay = Float.MAX_VALUE; int[] ids = entities.getData(); for (int i = 0; processed > i; i++) { int e = ids[i]; processDelta(e, acc); float remaining = getRemainingDelay(e); if(remaining <= 0) { processExpired(e); } else { offerDelay(remaining); } } acc = 0; } @Override protected void inserted(int entityId) { float remainingDelay = getRemainingDelay(entityId); processDelta(entityId, -acc); if(remainingDelay > 0) { offerDelay(remainingDelay); } } /** * Return the delay until this entity should be processed. * * @param entityId * entity * * @return delay */ protected abstract float getRemainingDelay(int entityId); @Override protected final boolean checkProcessing() { if (running) { acc += getTimeDelta(); return acc >= delay; } return false; } /** * Overridable method to provide custom time delta. */ protected float getTimeDelta() { return world.getDelta(); } /** * Process an entity this system is interested in. *

* Substract the accumulatedDelta from the entities defined delay. *

* * @param entityId * the entity to process * @param accumulatedDelta * the delta time since this system was last executed */ protected abstract void processDelta(int entityId, float accumulatedDelta); protected abstract void processExpired(int entityId); /** * Restarts the system only if the delay offered is shorter than the time * that the system is currently scheduled to execute at. *

* If the system is already stopped (not running) then the offered delay * will be used to restart the system with no matter its value. *

* 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. *

* * @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. *

* Returns zero (0) if the system is not running. * Use {@link #isRunning() isRunning()} before checking this value. *

* * @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. *

* Call offerDelay or restart to run it again. *

*/ public void stop() { this.running = false; this.acc = 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy