Double Tap Detection

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Double Tap Detection without Timers

This is an example to show one method of detecting a double tap of a movement key without using a timer. --Eyana Yohkoh 19:09, 27 August 2007 (PDT)

// Dash/dodge template script by Eyana Yohkoh
//
//
///////

// This script is an example of a way to detect a double tap on movement
// keys to trigger a function.
// There are multiple ways to detect a double tap, and this method quite
// possibly is not the best, but this certainly works.


// debugging stuff:
//
integer debug = FALSE;      // set this to TRUE if you want to hear debugging messages

debugging(string debugMsg)  // if debug is TRUE, then this is what will send messages
{                           // I put this in a function for ease of adding more debug messages
    if ( debug )            
    {
        llOwnerSay(debugMsg);
    }
}


// getting the time for the comparison
/////////
float strTime;          // used to store the current time 
float time;

getSeconds()
{
    string timestamp    = llGetTimestamp();                 
                                        // first part of getting the current time with milliseconds
                                        // this gives a strange time format so it was easier for me
                                        // to just grab the very end of the time to get the
                                        // fractional seconds.
    string subTime      = llGetSubString(timestamp, 19, 25);                                        

    float wallclock     = llGetWallclock();
                            // this gets the current time in seconds
                            // can't use this for a check without the above stuff because
                            // it does not do decimal places
                            
    strTime = (float)subTime + wallclock;
                            // appending milliseconds to the end of the rounded off seconds
                            // you could just do without this and test with seconds and milliseconds
                            // but that would cause problems with the comparison check for when
                            // double tapping at the cusp of a completed minute
                            
    debugging((string)strTime);             // debug message for testing purposes
}

// comparing the stored time with the current tap time
///////////

float storedTime;               // number will be stored at the end of a tap for comparison
float recentTime;               // stored immediately on tapping for comparing with the stored

compareTimes(float stored, float recent)        // find the difference between the times
{                                               // example use: compareTimes(storedTime, recentTime)
    time = recent - stored;
    debugging((string)recent + " - " + (string)stored + " = " +  (string)time);
}


resetStored()
{
    storedTime = 0;
}

float interval = 0.5;   // time between double taps
                        // default interval is 0.5 seems to be a good number
                        // 0.2 is too fast for some people, 1.0 is far too slow


doubleTap()
{
    if ( time < interval )
    {
        llSay(0, "Double tap detected");
    }
}

key avatar;
requestPerms()          // permissions we want to take:
{
    integer permissions = PERMISSION_TAKE_CONTROLS;
    llRequestPermissions(avatar, permissions);          // avatar is snagged when object is attached
}

takeControls()              // what controls to take. pared down for the example.
{
    integer controls    =   CONTROL_FWD;
                            
    llTakeControls(controls, TRUE, TRUE);
}

default
{
    on_rez(integer reznum)
    {
        llReleaseControls();            // release controls just in case
        resetStored();                  // reset all stored numbers
        debugging("Debug messages are turned on.");
    }

    run_time_permissions(integer perms)
    {
        if ( perms > 0 )            // if permissions are granted then take controls
        {
            takeControls();
        }
    }
    
    attach(key id)
    {
        if ( id != NULL_KEY )       // if id is NULL then it's not attached to a person!
        {
            avatar = id;            // store the key for later use without need to reset
            requestPerms();         // get permissions
        }
        else                        // since it's no longer attached, then no need for control
        {
            llReleaseControls();
        }
    }

    control(key id, integer held, integer change) 
    {
        integer pressed = held & change;
                    
        if ( pressed & CONTROL_FWD )
        {
            getSeconds();
            recentTime = strTime;                   // store the recent time 
                                                    // that was just found with getSeconds()
            compareTimes(storedTime, recentTime);   // comparing times
            doubleTap();                            // this will trigger for double taps!
            storedTime = recentTime;                // store the recent time for later in case
                                                    // this time was not a successful double tap
                                                    // but was possibly the first key press for the
                                                    // double tap
        }
    }
}


Double-tap detection - this example warps user at maximum velocity. [Functional code, paste to script, add to object, wear object, double tap forward key to test.]

//
// BETLOG Hax
// AEST: 20080801 2227 [SLT:  20080801 0527]
//=========================================================================
// ---LICENCE START---
// http://creativecommons.org/licenses/by-sa/3.0/
// ie: Attribution licence:
//   Give me credit by leaving it in the script I created.
//   Supply my original script with your modified version.
//   Refer to the wiki URL from which you copied this script.
//      https://wiki.secondlife.com/wiki/Double_Tap_Detection
// ---LICENCE END---
//=========================================================================

//----------------------------------
// SHARED CONFIGURATION
//----------------------------------
// CONFIGURATION
float       gDoubleTap          = 0.1;
//----------------------------------
// CORE CODE
integer     gWarpActive         = FALSE;
//----------------------------------
default
{
    state_entry()
    {
        if (llGetAttached())
            llRequestPermissions(llGetOwner(),PERMISSION_TAKE_CONTROLS);
    }
    attach(key id)
    {
        if (llGetAttached())
            llRequestPermissions(llGetOwner(),PERMISSION_TAKE_CONTROLS);
    }
    run_time_permissions(integer perms)
    {
        if(~perms & PERMISSION_TAKE_CONTROLS)
            llReleaseControls();
        else
        {
            llTakeControls(0
                | CONTROL_FWD
                | CONTROL_BACK
                | CONTROL_LEFT
                | CONTROL_RIGHT
//                | CONTROL_ROT_LEFT
//                | CONTROL_ROT_RIGHT
                | CONTROL_UP
                | CONTROL_DOWN
//                | CONTROL_LBUTTON
//                | CONTROL_ML_LBUTTON
            ,TRUE, TRUE);
            llOwnerSay("Ready - Doubletap frequency: "+(string)gDoubleTap);
        }
    }
    control(key id, integer pressed, integer change)
    {
        integer start = pressed & change;
        integer end = ~pressed & change;
        integer held = pressed & ~change;
        integer unheld = ~(pressed | change);
        //----------------------------------
        if (start & (CONTROL_FWD|CONTROL_BACK
                    |CONTROL_UP|CONTROL_DOWN
                    |CONTROL_LEFT//|CONTROL_ROT_LEFT
                    |CONTROL_RIGHT//|CONTROL_ROT_RIGHT
        ))
        {
            if (llGetTime() <= gDoubleTap)
            {
                if (-change == gWarpActive) //try to ensure only the key being *intentionally* double tapped is used.
                    gWarpActive = 1;
            }
        }
        //----------------------------------
        if (end & (CONTROL_FWD|CONTROL_BACK
                    |CONTROL_UP|CONTROL_DOWN
                    |CONTROL_LEFT//|CONTROL_ROT_LEFT
                    |CONTROL_RIGHT//|CONTROL_ROT_RIGHT
        ))
        {
            gWarpActive = -change;  //try to ensure only the key being *intentionally* double tapped is used.
            llResetTime();
        }
        //----------------------------------
        if (held & CONTROL_FWD)
        {
            if (gWarpActive > 0)
            {
                llPushObject(
                    llGetOwner()
                    ,llRot2Fwd(llGetRot())*0x7FFFFFFF//forward
                    ,ZERO_VECTOR
                    ,FALSE
                );
            }
        }
        //----------------------------------
        // ADD THE REST OF THE KEYS/DIRECTIONS HERE
//                    ,-llRot2Fwd(llGetRot())*0x7FFFFFFF //back
//                    ,llRot2Left(llGetRot())*0x7FFFFFFF //left
//                    ,-llRot2Left(llGetRot())*0x7FFFFFFF //right
//                    ,llRot2up(llGetRot())*0x7FFFFFFF //up
//                    ,-llRot2Up(llGetRot())*0x7FFFFFFF //down
    }
}