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
Names are now finished..
The code:
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
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:
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