1
\$\begingroup\$

Background

I have a variable time step, component based game, with components that collectively hold an entity's properties and different systems that act on entities with certain required components.

The player controls a ship that can fire bullets. I have an input system that works on entities with a PlayerControlComponent (nothing more specific yet) and creates an entity every frame if a key is held down.


Question

How should I manage limiting or throttling this so that it can't occur closer than 1 second apart in a reusable way?

\$\endgroup\$
3
\$\begingroup\$

Maybe I'm missing the point because it seems so simple but isn't something like this enough?

public class Component
{
    protected limit = 1.0f;
    private float timer = 0.0f;

    public virtual void Update(float dt)
    {
        timer += dt;
        if(timer >= limit)
        {
            timer -= limit;
            LimitedUpdate();
        }
    }

    public virtual void LimitedUpdate() {}
}

And then you override LimitedUpdate and put anything that you only want triggering from limit to limit seconds there.

Edit

And to fulfill the idea on your comment about making it into a centralized component and event driven (instead of polling driven):

public class ActionManager
{
    private struct ActionEntry
    {
        public Action Action;
        public float Limit;
        public float Timer;
    }

    private Dictionary<string, ActionEntry> entries = new Dictionary<string, ActionEntry>();

    public RegisterAction(string id, Action action, float limit = 1.0f)
    {
        // Note: I made Timer = limit so that the first call is 'free'
        entries[id] = new ActionEntry { Action = action, Limit = limit, Timer = limit };
    }

    public void TryAction(string id)
    {
        if(entries[id].Timer >= entries[id].Limit)
        {
            entries[id].Action();
            entries[id].Timer = 0.0f;
        }
    }

    public void Update(float dt)
    {
        foreach(var entry in entries)
        {
            entry.Value.Timer += dt;
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Something like that would probably work (with changes though, I only want it triggered by an event, not every 1 second). I was wondering if I could create a single system/object that could manage deciding whether to perform different actions or not, rather than managing the creation of your object for each possible action. \$\endgroup\$ – George Duckett Dec 20 '11 at 14:48
  • \$\begingroup\$ So you might RegisterAnAction specifying a GUID and rate limit, then whenever you wanted to do your action you might call TryDoAction which would either do the action, or not, depending on when the action was last performed. (Or maybe you'd call CanDoAction and perform the action outside the rate management object). \$\endgroup\$ – George Duckett Dec 20 '11 at 14:49
  • \$\begingroup\$ Simple enough, give me three minutes. \$\endgroup\$ – David Gouveia Dec 20 '11 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.