Double Tap Detection
| LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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)
<lsl> // 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
}
}
} </lsl>
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.]
<lsl> // // BETLOG Hax // AEST: 20080801 2227 [SLT: 20080801 0527] //---------------------------------- // 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())*0x0FFFFFFF //forward
,ZERO_VECTOR
,FALSE
);
}
}
//----------------------------------
// ADD THE REST OF THE KEYS/DIRECTIONS HERE
// ,-llRot2Fwd(llGetRot())*0x0FFFFFFF //back // ,llRot2Left(llGetRot())*0x0FFFFFFF //left // ,-llRot2Left(llGetRot())*0x0FFFFFFF //right // ,llRot2up(llGetRot())*0x0FFFFFFF //up // ,-llRot2Up(llGetRot())*0x0FFFFFFF //down
}
} </lsl>