# Best Method To Track Length and Time of Touches

Hi All,
My latest project involves the development of a system to store and track the times that a user has touched the screen.
I ran in to an issue with the storing of the touch data - the time began and the time ended. I’ve found a solution to my problem (just insert the times into a table and if it’s odd its when the touch began, if it’s even, it’s when the touch ended), however it is very crude and will not work for an larger version of the project.
Here is my code:

``````function setup()
input = {}
numTouches = 0
isTouched = false
end

-- This function gets called once every frame
function draw()
background(255, 255, 255, 255)
stroke(0, 0, 0, 255)
lineCapMode(ROUND)
strokeWidth(10)
if isTouched then
if numTouches == 0 then
print("touch ended")
table.insert(input, ElapsedTime)
isTouched = false
end
else
if numTouches > 0 then
print("touch began")
table.insert(input, ElapsedTime)
isTouched = true
end
end
local m = 100
for i = 1, math.ceil(#input / 2) do
local began = ElapsedTime - input[i * 2 - 1]
local ended = ElapsedTime - (input[i * 2] or ElapsedTime)
line(WIDTH * .75 - began * m, HEIGHT / 2, WIDTH * .75 - ended * m, HEIGHT / 2)
end
strokeWidth(2)
line(WIDTH * .75, 0, WIDTH * .75, HEIGHT )
end

function touched(touch)
if touch.state == BEGAN then
numTouches = numTouches + 1
elseif touch.state == ENDED then
numTouches = numTouches - 1
end
end
``````

The specifically problematic part is the loop `for i = 1, math.ceil(#input / 2) do`

Any suggestions on how to refine this? Preferably on the structure of the data?

@Jordan Maybe something like this. Just save the touch state and the time in a table. Then you can read the table and look for the began (0) and ended (2) values and subtract the times to get the length of the touch. This doesn’t save anything when the state is MOVING. I print the table when the touch state is ENDED, but you can do it whenever you want.

``````function setup()
tab={}
end

function draw()
end

function touched(t)
if t.state~=MOVING then
table.insert(tab,vec2(t.state,os.time()))
end
if t.state==ENDED then
output.clear()
for a,b in pairs(tab) do
print(b)
end
end
end
``````

Thanks @Dave1707, a more elegant solution, but I realized I was not being too clear in my original post: I want to be store the data in a more organized format in that table (preferably {time began, time ended}) but I can’t see a way to do that which still allows me to interact with the data in real time - I can’t process a touch that isn’t finished with an alternative system

@Jordan Here’s a version the saves the BEGAN time, the ENDED time, and the difference between the two.

``````function setup()
tab={}
end

function draw()
end

function touched(t)
if t.state==BEGAN then
bTime=os.time()
end
if t.state==ENDED then
table.insert(tab,vec3(bTime,os.time(),os.time()-bTime))
output.clear()
for a,b in pairs(tab) do
print(b.x,b.y,b.z)
end
end
end
``````

How are you planning on handling multitouch? Do you want to process multiple touches separately? Or, if only processing one touch at a time, do you exclude all subsequent touches once a touch has began, or let a subsequent touch interrupt the first finger that was on the screen?

@yojimbo2000, This is all for a prototype morse code keyboard that I’m working on, so I want it to measure time the screen is touched, regardless of how many fingers (as I used `numTouches > 0`in my original code)

@Jordan It’s easy to help when we know exactly what you’re trying to do. Here’s an example of a morse code key. You can adjust the time between key touches and the time between letters. A table of letters can be added to decode the dots and dashes to a letter. This doesn’t go to multiple lines. It’s more of an example for the key timing.

``````displayMode(FULLSCREEN)

function setup()
textMode(CORNER)
parameter.number("clicks",.1,1,.2)   -- time between clicks
parameter.number("letters",.1,1,.5)  -- time between letters
font("Courier-Bold")
tab={}
tm=0
eTime=0
end

function draw()
background(0)
fill(255)
str=string.format("Dot < %.2f seconds, Dash > %.2f seconds",clicks,clicks)
text(str,100,HEIGHT-100)
str=string.format("Seconds between letters %.2f",letters)
text(str,100,HEIGHT-130)
tm=tm+DeltaTime
for a,b in pairs(tab) do
if b=="." then
text(b,a*10,500)
else
text(b,a*10,498)
end
end
end

function touched(t)
if t.state==BEGAN then
bTime=tm
if bTime-eTime>letters then
table.insert(tab," ")
end
end
if t.state==ENDED then
eTime=tm
if tm-bTime>clicks then
table.insert(tab,"-")
else
table.insert(tab,".")
end
end
end
``````

@Dave1707 I’m one step ahead of you I’ve already got the code to fully interpret morse code input, but I’m trying to do away with the need for a set length for the dot length, so it dynamically works out the speed at which one is typing in morse and able to then figure out the dits and dahs - hence the need to store the touches and their lengths so I can compare them in real time

I can post the current working version of my code if you’re interested, but it’s still very rusty

@Jordan It would be interesting to see your code, but maybe I should wait until you get it finalized. I’ve never played around with morse code other than seeing tables with the letters and the corresponding dots and dashes. I guess someone who was good at morse code could do it really fast, hence a shorter duration for the dots and dashes. Maybe instead of storing the information in a table and having to go thru it, you could just have 2 averages, one for dots and one for dashes. As someone increases their speed, the average times would decrease. To determine the dots and dashes, they would be within a certain plus or minus amount of their average times.

Here is my working demo (without automatic speed)

Code:

``````-- morse

-- Use this function to perform your initial setup
function setup()
parameter.watch("morse.buffer")
parameter.watch("morse.lastTouch")
music("Project:morse", true)
music.volume = 0
end

-- This function gets called once every frame
function draw()
music.volume = (morse.numTouches > 0 or (morse.lastTouch and (ElapsedTime - morse.lastTouch) < morse.unit)) and 1 or 0
background(0)
morse:update()

fill(255, 255, 255, 255)
font("SourceSansPro-Regular")
fontSize(30)
text(morse.text .. (morse.code[morse.buffer] or ""), WIDTH / 2, HEIGHT / 2)
text(morse.buffer, WIDTH / 2, HEIGHT / 4 * 3)

if morse.numTouches ~= 0 then
ellipse(CurrentTouch.x, CurrentTouch.y, 100)
end
end

function touched(touch)
if touch.state == BEGAN then
morse:newTouch(touch)
elseif touch.state == ENDED then
morse:endTouch(touch)
end
end

morse = {}

morse.code = {
[".-"] = "a",
["-..."] = "b",
["-.-."] = "c",
["-.."] = "d",
["."] = "e",
["..-."] = "f",
["--."] = "g",
["...."] = "h",
[".."] = "i",
[".---"] = "j",
["-.-"] = "k",
[".-.."] = "l",
["--"] = "m",
["-."] = "n",
["---"] = "o",
[".--."] = "p",
["--.-"] = "q",
[".-."] = "r",
["..."] = "s",
["-"] = "t",
["..-"] = "u",
["...-"] = "v",
[".--"] = "w",
["-..-"] = "x",
["-.--"] = "y",
["--.."] = "z",
["-----"] = "0",
[".----"] = "1",
["..---"] = "2",
["...--"] = "3",
["....-"] = "4",
["....."] = "5",
["-...."] = "6",
["--..."] = "7",
["---.."] = "8",
["----."] = "9",
[".-.-"] = "\
",
[".-.-.-"] = ".",
["--..--"] = ",",
["..--.."] = "?",
["-.-.--"] = "!",

}

morse.touches = {}
morse.numTouches = 0
morse.lastTouch = nil
morse.unit = 0.12
morse.buffer = ""
morse.text = ""
function morse:newTouch(touch)

self.touches[touch.id] = 0
self.numTouches = morse.numTouches + 1
end

function morse:update()
for k, v in pairs(self.touches) do
self.touches[k] = self.touches[k] + DeltaTime
end
if self.numTouches == 0 then
if self.lastTouch then
self:processSpace(ElapsedTime - self.lastTouch)
end
end
end

function morse:endTouch(touch)
self:processTouch(self.touches[touch.id])
self.touches[touch.id] = nil
self.numTouches = self.numTouches - 1
if self.numTouches == 0 then
self.lastTouch = ElapsedTime
end
end

function morse:processTouch(t)
if t < self.unit then
self.buffer = self.buffer .. "."
else
self.buffer = self.buffer .. "-"
end
end

function morse:processSpace(t)
if t > self.unit * 7 then
elseif t > self.unit * 3 then
self:processBuffer()
end
end

function morse:processBuffer()
if morse.code[self.buffer] then
print(morse.code[self.buffer], self.buffer)
morse.text = morse.text .. morse.code[self.buffer]
elseif self.buffer == "........" then
morse.text = morse.text:sub(1, -3)
end
self.buffer = ""
end