using System; namespace Utility { /// /// An object that invokes an action after an amount of time has elapsed and /// optionally continues repeating until told to stop. /// public sealed class Timer { private static readonly Pool timers = new Pool(10, t => t.valid) { // Initialize is invoked whenever we get an instance through New() Initialize = t => { t.valid = true; t.time = 0f; }, // Deinitialize is invoked whenever an object is reclaimed during CleanUp() Deinitialize = t => { t.tick = null; t.Tag = null; } }; private bool valid; private float time; private float tickLength; private bool repeats; private Action tick; /// /// Gets or sets some extra data to the timer. /// public object Tag { get; set; } /// /// Gets whether or not this timer repeats. /// public bool Repeats { get { return repeats; } } /// /// Gets the length of time (in seconds) between ticks of the timer. /// public float TickLength { get { return tickLength; } } /// /// Creates a new Timer. /// /// The amount of time between the timer's ticks. /// Whether or not the timer repeats. /// An action to perform when the timer ticks. /// The new Timer object or null if the timer pool is full. public static Timer Create(float tickLength, bool repeats, Action tick) { if (tickLength <= 0f) throw new ArgumentException("tickLength must be greater than zero."); if (tick == null) throw new ArgumentNullException("tick"); // get a new timer from the pool Timer t = timers.New(); t.tickLength = tickLength; t.repeats = repeats; t.tick = tick; return t; } /// /// Stops the timer. /// public void Stop() { valid = false; } /// /// Updates all the Timers. /// /// The elapsed time (in seconds) to advance the timers. Generally you want to pass in (float)gameTime.ElapsedGameTime.TotalSeconds from your main Game class. public static void Update(float dt) { for (int i = 0; i < timers.ValidCount; i++) { Timer t = timers[i]; // if a timer is stopped manually, it may not // be valid at this point so we skip it. if (!t.valid) continue; // update the timer's time t.time += dt; // if the timer passed its tick length... if (t.time >= t.tickLength) { // perform the action t.tick(t); // subtract the tick length in case we need to repeat t.time -= t.tickLength; // if the timer doesn't repeat, it is no longer valid if (!t.repeats) t.valid = false; } } // clean up any invalid timers timers.CleanUp(); } } }