Double Tap Detection

====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
 }
}
Category:LSL Examples