TimedLoop

Scripts

14 years
edited 8 years
All right, after the PeriodicLoopModule failure, this is a simpler version that is less flexible but should work, it is for structs that are exclusive for looping and will conflict with stuff that require you not to call .destroy but another method.

It is a module you implement in a struct to do the whole array+loop thing that we always do in spells. Only that this time you won't have to code it all the time... an example:

Only disadvantage against doing the loop manually is that it will do a function call (not TriggerEvaluate) for each instance in the loop. Differences with things like TT is the OOPness and the lack of TriggerEvaluate, though it uses a timer per struct type, wonder if that's important.

Usage sample
Code (jass) Select
struct moveUnit

    unit u

    //=====================================================
    // You need to code an onTimedLoop method before
    // implementing the module.
    //
    private method onTimedLoop takes nothing returns boolean
        //instance's timer expired:
        // This will just move a unit's x coordinate with
        // a speed of 100 until it reaches 5000.0

        call SetUnitX(u, GetUnitX(u) + 100.0* TimedLoop_PERIOD )
        // notice the use of the TimedLoop_PERIOD constant
        // since it may be tweaked by the user...


        if ( GetUnitX(u) >= 5000) then
            return TimedLoop_STOP
        endif

     return TimedLoop_CONTINUE

     //You are free to/should use false and true instead of the
     //constants.
    endmethod

    implement TimedLoop //This does the module magic

    static method create takes unit u returns moveUnit
     local moveUnit m= moveUnit.allocate()
        set m.u = u
        call m.startTimedLoop() //The module works by
        // creating a startTimedLoop method that will
        // do all the dirty work and end up calling
        // .onTimedLoop...
        //
     return m
    endmethod

endstruct
//call moveUnit.create(GetTriggerUnit()) and see...


Names are now finished..

The code:
Code (jass) Select
library TimedLoop
//********************************************************
//* TimedLoop
//* ---------
//*
//* Requires jasshelper 0.9.G.1 or greater.
//*
//*   A library + module that are meant to make those
//* array + timer loops easy, yet still faster than
//* other alternatives meant to be easy (In other words
//* no TriggerEvaluate is involved).
//*
//* The OOPness is interesting.
//*
//*  Before implementing TimedLoop
//* your struct needs an onTimedLoop method that takes
//* nothing and returns boolean, if the method
//* returns false, the instance will get removed
//* from the loop and destroyed, else it will continue,
//* think of it as if the call asks the method a
//* question: "Should I continue the loop afterwards?"
//*
//* Alternatively, if you are not convinced, you may
//* use the TimedLoop_CONTINUE and TimedLoop_STOP
//* constants in the method's returns.
//*
//*   After implementing TimedLoop, you can call
//* the startTimedLoop method to add the periodic event
//* to that instance, only call it once per instance.
//*
//* I recommend to call implement just bellow the
//* declaration of the onLoop method, else it will
//* actually use TriggerEvaluate, which is lame. Remind
//* me to implement a topsort in jasshelper.
//*
//*  If you feel the need to destroy the struct outside
//* the loop, well, you'll have to add a flag to it so
//* you send a message to onLoop to make it return false.
//* A more complicated module to allow that easily would
//* come later.
//*
//********************************************************

//========================================================
// config:

    globals
     public constant real    PERIOD = 0.025
     // A lower value and everything using the module will
     // look better, yet performance will drop.
    endglobals

//========================================================
// implementation:
//
   globals
    public constant boolean STOP     = false
    public constant boolean CONTINUE = true
   endglobals
   
   
   //=========================== 
   module TimedLoop
   // god bless private module members.
   //
      private static thistype array V        // The array
      private static integer        N = 0    // The count
      private static timer          T = null // the timer, one per
                                             // struct that implements this
     
      private static method onExpire takes nothing returns nothing
       local integer  n    = 0
       local thistype this // yay for odd-sounding syntax constructs
       local integer  i    = 0
       
          loop
              exitwhen (i== thistype.N)
              set this = .V[i]
              if ( this.onTimedLoop() == CONTINUE ) then
                  set .V[n] = this
                  set n=n+1
              else
                  call this.destroy()
              endif
              set i=i+1
          endloop
          set thistype.N = n
          if (n== 0) then
              call PauseTimer(.T)
          endif
                 
      endmethod
     
      public method startTimedLoop takes nothing returns nothing
         set .V[.N] = this
         set .N=.N + 1
         if (.N == 1) then
             if (.T == null) then
                 set .T = CreateTimer()
             endif
             call TimerStart(.T, PERIOD, true, function thistype.onExpire)
         endif
      endmethod
     
   endmodule


endlibrary