Mutilple gestures

I know I’m asking many questions without very many results for them and I apologize. But this time my curiosity leads me to multiple gestures.

If I wanted a Tap to say do a light attack
A tap and hold for a strong attack
And swipe for dodge

Is that possible and how would I do so?

these types of inputs are all about timing,

tap and hold , so how long until you consider “hold = true?”

and swipe is about changing x,y value within a certain time and distance

if touch.state == BEGAN then
   myTimer = 0
   startX = touch.x
elseif touch.state  ~= ENDED then
   myTimer = myTimer + DeltaTime
   if myTimer > myLimit then
     held = true
   end
   if held and math.abs(startX - touch.x > 20) then
     swipe = true
   end
else
  held = false
end

this gets a bit more complex with multiple fingers

@Dezmo here is a basic touch tracker code I’ve had kicking around for a few years. I think it predates the new gesture functions in Codea, but adopts the same approach as @skar talks about.

THERES TIMERS?!?
excellent I really appreciate it
I didn’t think to add delta time as a timer I’ll begin using this now matter of fact

@West THAT TOUCH TRACKER IS HARD ASH
I’m gonna be dissecting it for some time now to learn from it. Really loving the lock on animation after holding on for a moment

@West - great little demo and cool routines. Will take a little digesting but looks like a lot of useful code there.

By the way, stopped the demo and logged into Safari on the forum to post this note and Codea crashed. Not sure why.

@dave1707 @Simeon - please note, posted the crash report. Had a couple like this recently, do you think it could be changes in iOS or the direction Codea is now moving in?

i also came across this somewhere and i can’t remember who to credit, but it allows for two fingers to control pinch zoom and panning


GestureManager = class()
local function create_vec2_from_vec3(v3)
  return vec2(v3.x, v3.y)
end

local function get_distance_vec3(touch1, touch2)
  local touch1_2d = create_vec2_from_vec3(touch1)
  local touch2_2d = create_vec2_from_vec3(touch2)
  return touch1_2d:dist(touch2_2d)
end

function GestureManager:init()
  self.touch1 = vec3(0, 0, 0)
  self.touch2 = vec3(0, 0, 0)
  self.scale = 1
  self.translationX = 0
  self.translationY = 0
end

function GestureManager:apply()
  print(self.scale, ":", self.translationX, self.translationY)
end

function GestureManager:touched(touch)
  if touch.state == BEGAN then
    local touch_pos = vec3(touch.x, touch.y, touch.id)
    if self.touch1.z == 0 and self.touch2.z ~= touch_pos.z then
      self.touch1 = touch_pos
    elseif self.touch1.z ~= 0 and self.touch1.z ~= touch_pos.z then
      self.touch2 = touch_pos
    end
  elseif touch.state == CHANGED then
    local old_touch1 = self.touch1
    local old_touch2 = self.touch2
    local touch_pos = vec3(touch.x, touch.y, touch.id)
    if self.touch1.z == touch.id then
      self.touch1 = touch_pos
    elseif self.touch2.z == touch.id then
      self.touch2 = touch_pos
    end
    if self.touch1.z ~= 0 and self.touch2.z ~= 0 then
      local old_center = vec2((old_touch1.x + old_touch2.x) / 2, (old_touch1.y + old_touch2.y) / 2)
      local new_center = vec2((self.touch1.x + self.touch2.x) / 2, (self.touch1.y + self.touch2.y) / 2)
      local old_distance = get_distance_vec3(old_touch1, old_touch2)
      local distance = get_distance_vec3(self.touch1, self.touch2)
      local scale_multiplier = distance / old_distance
      local new_scale = self.scale / scale_multiplier
      --local old_width = WIDTH / self.scale
      --local new_width = WIDTH / new_scale
      --local width_diff = new_width - old_width
      --self.translationX = self.translationX + new_center.x / WIDTH * width_diff
      --local old_height = HEIGHT / self.scale
      --local new_height = HEIGHT / new_scale
      --local height_diff = new_height - old_height
      --self.translationY = self.translationY + new_center.y / HEIGHT * height_diff
      self.translationX = self.translationX + (new_center.x - old_center.x) * new_scale
      self.translationY = self.translationY + (new_center.y - old_center.y) * new_scale
      self.scale = new_scale
      self:apply()
    end
  elseif touch.state == ENDED then
    self.touch1 = vec3(0, 0, 0)
    self.touch2 = vec3(0, 0, 0)
  end
end


Here’s an example that shows a short press, a long press, a swipe distance, and a swipe angle. The swipe angle is 0 to the right, 90 at the top, going counter clockwise.

viewer.mode=FULLSCREEN

function setup()
    s=require("socket")
    pressDuration=.25   -- time cutoff between a short and long press
    swipeLimit=20       -- distance limit for a swipe
    shortPress,longPress,swipeAngle,swipeDist=0,0,0,0
    fill(255)
end

function draw()
    background()
    text("Short Press  "..shortPress,WIDTH/2,HEIGHT/2)
    text("Long Press   "..longPress,WIDTH/2,HEIGHT/2-50)
    text("Swipe Distance   "..swipeDist,WIDTH/2,HEIGHT/2-100)
    text("Swipe Angle    "..swipeAngle,WIDTH/2,HEIGHT/2-150)
end

function touched(t)
    touchControl(t)
end

function touchControl(t)
    if t.state==BEGAN then
        shortPress,longPress,swipeAngle,swipeDist=0,0,0,0
        st=s:gettime()
        tx,ty=t.x,t.y
    end
    if t.state==ENDED then
        local diff=s:gettime()-st
        if diff<pressDuration then
            shortPress=diff
        else
            longPress=diff
        end
        swipeDist=vec2(t.x,t.y):dist(vec2(tx,ty))
        if swipeDist>swipeLimit then
            swipeAngle=(math.deg(math.atan2(t.y-ty,t.x-tx))+360)%360
        end
    end   
end