TimerV

Version:

1.0

Added on:

22 Dec 2019 01:16

Tags:

Description:
Class that lets you schedule a function to be called later on with just a single line. No need to keep track of the timer manually, it will call your function automatically when the time has elapsed. Instructions and examples are included.

TimerV(time, callback);
  1. /*
  2.   Usage: To schedule a function to be called at some point in the future, call
  3.   the TimerV constructor with the desired delay and function as arguments, e.g.:
  4.  
  5.     void myAlert() {
  6.       jjAlert("A second has passed.");
  7.     }
  8.     void onLevelLoad() {
  9.       TimerV(70, myAlert); //calls myAlert after one second (70 ticks)
  10.     }
  11.  
  12.   Anonymous functions (or delegates) may be used instead:
  13.  
  14.     void onLevelLoad() {
  15.       TimerV(70, function(){ jjAlert("A second has passed."); }); //same effect as above
  16.     }
  17.    
  18.   For a recurring event, have the called function construct another timer for itself:
  19.  
  20.     void morphEveryone() {
  21.       for (int i = 0; i < jjLocalPlayerCount; ++i)
  22.         jjLocalPlayers[i].morph(true);
  23.       TimerV(5 * 70, morphEveryone);
  24.     }
  25.     void onLevelLoad() {
  26.       morphEveryone(); //morphs all local players every five seconds
  27.     }
  28.    
  29.   To pass one or more arguments to the delayed function, use a function that takes a single
  30.   dictionary@ as its sole argument, and pass that dictionary@ to the TimerV constructor:
  31.  
  32.     void onFunction0(uint8 triggerID) {
  33.       if (!jjTriggers[triggerID]) {
  34.         jjTriggers[triggerID] = true;
  35.         TimerV( //turns on, then off, whichever trigger was specified by the offset parameter of the Text event
  36.           2 * 70,
  37.           function(arguments) {
  38.             jjTriggers[uint8(arguments["ID"])] = false;
  39.           },
  40.           dictionary = {{"ID",triggerID}}
  41.         );
  42.       }
  43.     }
  44.    
  45.   Another use of a dictionary argument is to limit the number of times the function is called:
  46.  
  47.     void playSound(dictionary@ arguments) {
  48.       jjSamplePriority(SOUND::COMMON_COIN);
  49.       int count = int(arguments["count"]) - 1;
  50.       if (count > 0) {
  51.         arguments["count"] = count;
  52.         TimerV(40, playSound, arguments);
  53.       }
  54.     }
  55.     void onLevelLoad() {
  56.       playSound(dictionary = {{"count",5}}); //plays the COMMON_COIN sample exactly five times
  57.     }
  58.    
  59.   As mentioned, the TimerV lines are actually constructors, not regular functions. If you have any
  60.   reason to keep a TimerV object around after its construction, e.g. if there's a possibility you
  61.   might need to cancel it, it provides the following API:
  62.  
  63.     const bool Active
  64.       true iff this timer is still running
  65.      
  66.     const int Elapsed
  67.       How many ticks have passed since the construction, or -1 if Active is false
  68.      
  69.     const int Total
  70.       The original time parameter passed to the constructor, as a reminder, or -1 if Active is false
  71.      
  72.     const int Remaining
  73.       (Total - Elapsed), or -1 if Active is false
  74.      
  75.     bool Paused
  76.       While true, this timer will not advance, though Active will remain true
  77.      
  78.     bool Stop()
  79.       Stops the timer early (WITHOUT executing the function) and returns true, or returns false if Active was false
  80. */
  81.  
  82.  
  83. funcdef void TimerVDictionaryFunction(dictionary@);
  84. class TimerV : jjBEHAVIORINTERFACE {
  85.   TimerV(int time, jjVOIDFUNC@ callback) {
  86.     @_callback = @callback;
  87.     _start(time);
  88.   }
  89.   TimerV(int time, TimerVDictionaryFunction@ callback, dictionary@ arguments) {
  90.     @_callbackWithArguments = @callback;
  91.     @_arguments = @arguments;
  92.     _start(time);
  93.   }
  94.   bool get_Active() const {
  95.     return cast<jjBEHAVIORINTERFACE@>(_object.behavior) is this;
  96.   }
  97.   int get_Elapsed() const {
  98.     if (Active) return _object.age;
  99.     return -1;
  100.   }
  101.   int get_Total() const {
  102.     if (Active) return _object.counter;
  103.     return -1;
  104.   }
  105.   int get_Remaining() const {
  106.     if (Active) return _object.counter - _object.age;
  107.     return -1;
  108.   }
  109.   bool Stop() {
  110.     if (Active && _object.age < _object.counter) {
  111.       _object.delete();
  112.       return true;
  113.     }
  114.     return false;
  115.   }
  116.   bool Paused = false;
  117.  
  118.  
  119.  
  120.  
  121.  
  122.   private jjVOIDFUNC@ _callback = null;
  123.   private TimerVDictionaryFunction@ _callbackWithArguments;
  124.   private dictionary@ _arguments;
  125.   private jjOBJ@ _object;
  126.   private int _startTime;
  127.   private void _start(int time) {
  128.     if (time > 0) {
  129.       @_object = jjObjects[jjAddObject(OBJECT::BEES, -1000, -1000, 0, CREATOR::OBJECT, BEHAVIOR::BEES)];
  130.       _object.behavior = this;
  131.       _object.counter = time;
  132.       _object.age = 0;
  133.       _object.playerHandling = HANDLING::PARTICLE;
  134.       _object.deactivates = false;
  135.       _startTime = jjGameTicks;
  136.     } else {
  137.       @_object = jjObjects[0]; //avoid null pointer access
  138.       _pickCallback();
  139.     }
  140.   }
  141.   private void onBehave(jjOBJ@ obj) {
  142.     if (!Paused && jjGameTicks > _startTime && obj is _object && ++_object.age >= _object.counter) {
  143.       _pickCallback();
  144.       _object.delete();
  145.     }
  146.   }
  147.   private void _pickCallback() {
  148.     if (_callback !is null)
  149.       _callback();
  150.     else
  151.       _callbackWithArguments(_arguments);
  152.   }
  153. }