Jump to content

Floating point multi timer


ItHadToComeToThis
 Share

You are about to reply to a thread that has been inactive for 1585 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I needed to write myself a multi timer so thought I would post it here for you fine people. Chances are it can probably be improved, if so, post your improvements in the comments.

 

float timerA=2.0;
float timerB=3.3;
float timerC=7.0;

float decimalPlace(float d, integer p){
    string s=(string)d;
    s=llDeleteSubString(s,llSubStringIndex(s,".")+p,-1);
    return ((float)s);
}

float div(float a, float b){
    return a-b*llFloor(a/b);
}

integer checkTimer(float mTimer){
    if(div(decimalPlace(llGetTime(),2),mTimer)==0.0){
        return 1;
    }
    return 0;
}

default{
    state_entry(){
        llResetTime();
        llSetTimerEvent(0.1);
    }
    timer(){
        //Timer A
        if(checkTimer(timerA)){
            llOwnerSay("TIMER A : "+(string)decimalPlace(llGetTime(),2));
        }
        //Timer B
        if(checkTimer(timerB)){
            llOwnerSay("TIMER B : "+(string)decimalPlace(llGetTime(),2));
        }
        //Timer C
        if(checkTimer(timerC)){
            llOwnerSay("TIMER C : "+(string)decimalPlace(llGetTime(),2));
        }
    }
}
/* RETURNS
[13:16] Object: TIMER A : 2.000000
[13:16] Object: TIMER B : 3.300000
[13:16] Object: TIMER A : 4.000000
[13:16] Object: TIMER A : 6.000000
[13:16] Object: TIMER B : 6.600000
[13:16] Object: TIMER C : 7.000000
[13:16] Object: TIMER A : 8.000000
[13:16] Object: TIMER A : 10.000000
[13:16] Object: TIMER A : 12.000000
[13:16] Object: TIMER B : 13.200000
[13:16] Object: TIMER A : 14.000000
[13:16] Object: TIMER C : 14.000000
[13:16] Object: TIMER A : 16.000000
[13:16] Object: TIMER A : 18.000000
[13:16] Object: TIMER A : 20.000000
[13:16] Object: TIMER C : 21.000000
[13:16] Object: TIMER A : 22.000000
*/

 

Link to comment
Share on other sites

some thoughts

casting float to string always results in 6 chars following the decimal point. For an efficiency gain we can remove the llSubStringIndex() function call and get the same result

float decimalPlace(float d, integer p)
{
   return (float)llDeleteSubString((string)d, p-6, -1);
}


checkTimer() evaluates to TRUE or FALSE so we can do an inline evaluation for a tiny gain:

integer checkTimer(float mTimer)
{
    return (div(decimalPlace(llGetTime(), 2), mTimer) == 0.0);
}

 

and a different way to do this. A multi-timer that uses a ticker

float TICK_PERIOD = 0.1;  // tick the timer every 0.1 seconds
integer TimerA = 20;    // fire timerA every 20 * TICK_PERIOD = 2.0 seconds
integer TimerB = 33;    // fire timerB every 33 * TICK_PERIOD = 3.3 seconds
integer TimerC = 70;    // fire timerC every 70 * TICK_PERIOD = 7.0 seconds

integer ticker;   // add 1 to ticker every TICK_PERIOD
integer range;    // prevent the ticker from overflowing 

default
{
    state_entry()
    {
        llResetTime();
        range = TimerA * TimerB * TimerC;
        llSetTimerEvent(TICK_PERIOD);
    }

    timer()
    {
        ticker = (++ticker) % range; 
        if (!(ticker % TimerA)) // fire TimerA
        {
            llOwnerSay("TimerA: " + (string)llGetTime());
        }
        if (!(ticker % TimerB)) // fire TimerB
        {
            llOwnerSay("TimerB: " +  (string)llGetTime());
        }
        if (!(ticker % TimerC)) // fire TimerC
        {
            llOwnerSay("TimerC: " +  (string)llGetTime());
        }
    }
}

 

 

 

 

 

 

  • Like 1
Link to comment
Share on other sites

7 hours ago, Mollymews said:

 

That’s an interesting way to do it and thanks for the comments, il make changes to my one. One thing I realised I never added a way to stop the timers on mine so thinking I may add that later. Debating whether to use lists or if I can use a bit wise switch to keep track of the timer numbers. Or maybe I am over thinking it

Link to comment
Share on other sites

5 hours ago, ItHadToComeToThis said:

One thing I realised I never added a way to stop the timers on mine so thinking I may add that later

Debating whether to use lists or if I can use a bit wise switch to keep track of the timer numbers. Or maybe I am over thinking it

some thoughts on these

with floats then we have to guard against precision errors. Example this:

div(decimalPlace(llGetTime(), 2), mTimer) == 0.0;

llGetTime() cannot be exactly 9.9. It is 9.913491. Which after casting and trimming returns as 9.91

9.91 modulus 3.3 is 0.01

0.01 != 0.0 so the function returns FALSE when for the purposes of the timer it should return TRUE

we can fix this by bounding the precision deviation to some range. Example:

div(decimalPlace(llGetTime(), 2), mTimer) <= 0.05; // where 0.05 is the deviation we have chosen


with managing the timers

a way it can be done is to set the timer values to 0.0 when not used. Checking for this in checkTimer() which also prevents a division by zero error in the div() function. Example:

integer checkTimer(float mTimer)
{
   if (mTimer <= 0.0)
      return FALSE;
   return div(decimalPlace(llGetTime(), 2), mTimer) <= 0.05;
}

to start/stop the timer event then a way is to use the sum total of the individual timers. Example:

llSetTimerEvent( 0.1 * (float)(TimerA + TimerB + TimerC > 0.0));
// when any of the timers are greater than 0.0 then
// 0.1 * (float)TRUE = 0.1
// when they are all 0.0 then
// 0.1 * (float)FALSE = 0.0

 

on using a list for the timers rather than named variables then this is the way I prefer also

as with a list we can add/remove timers dynamically at runtime, which we often need to do when making multi-player and/or multi-level games

 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1585 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...