Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --# Library
- Flickable
- = {angleOffset = 0, constant = false, useCorners = true}
- local touches = {}
- local debugtouch = {}
- local sign = function(n)
- return n / math.abs(n)
- end
- local inRange = function(x, y, s, px, py)
- --return math.abs(x - px) <= w / 2 and math.abs(y - py) <= h / 2
- return vec2(x, y):dist(vec2(px, py)) <= s
- end
- function getDebugFromID(id)
- return debugtouch[id]
- end
- function getDebugFromTouch(touch)
- return debugtouch[touch.id]
- end
- function getTouchFromID(id)
- return touches[id]
- end
- function getTouchFromDebug(deb)
- return touches[deb.id]
- end
- function getNameFromMotion(x, y, human)
- local ret = ""
- if y > 7.5 then
- ret = ret .. "up"
- end
- if y < -7.5 then
- ret = ret .. "down"
- end
- if x > 7.5 then
- if human and ret ~= "" then
- ret = ret .. "-"
- end
- ret = ret .. "right"
- end
- if x < -7.5 then
- if human and ret ~= "" then
- ret = ret .. "-"
- end
- ret = ret .. "left"
- end
- return ret
- end
- function getNameFromAngle(angle, human)
- local ret = ""
- local a = angle + Flickable.angleOffset
- local tolerance = 45
- if Flickable.useCorners then
- tolerance = 67.5
- end
- if a > 90 - tolerance and a < 90 + tolerance then
- ret = ret .. "up"
- end
- if a < -90 + tolerance and a > -90 - tolerance then
- ret = ret .. "down"
- end
- if a < tolerance and a > -tolerance then
- if human and ret ~= "" then
- ret = ret .. "-"
- end
- ret = ret .. "right"
- end
- if a > 180 - tolerance or a < -180 + tolerance then
- if human and ret ~= "" then
- ret = ret .. "-"
- end
- ret = ret .. "left"
- end
- return ret
- end
- function getBoolFromMotion(x, y)
- return {up = y > 7.5, down = y < -7.5, right = x > 7.5, left = x < -7.5}
- end
- function getBoolFromAngle(angle)
- local a = angle + Flickable.angleOffset
- local tolerance = 45
- if Flickable.useCorners then
- tolerance = 67.5
- end
- return {up = a > 90 - tolerance and a < 90 + tolerance, down = a < -90 + tolerance and a > -90 - tolerance, right = a < tolerance and a > -tolerance, left = a > 180 - tolerance or a < -180 + tolerance}
- end
- local nextf = function(f)
- tween.delay(0, function()
- pcall(f)
- end)
- end
- local handle = function(touch)
- touches[touch.id] = touch
- if touch.state == BEGAN and debugtouch[touch.id] == nil then
- debugtouch[touch.id] = {id = touch.id, start = ElapsedTime, startX = touch.x, startY = touch.y, motX = 0, motY = 0, long = false}
- end
- local deb = debugtouch[touch.id]
- local still = inRange(deb.startX, deb.startY, 20, touch.x, touch.y) and math.abs(deb.motX) <= 15 and math.abs(deb.motY) <= 15
- if debugtouch[touch.id] ~= nil then
- if sign(touch.deltaX) ~= sign(deb.motX) then
- debugtouch[touch.id].motX = debugtouch[touch.id].motX * 0.2 + 0.8 * touch.deltaX
- else
- debugtouch[touch.id].motX = debugtouch[touch.id].motX * 0.9 + 0.1 * touch.deltaX
- end
- if sign(touch.deltaY) ~= sign(deb.motY) then
- debugtouch[touch.id].motY = debugtouch[touch.id].motY * 0.2 + 0.8 * touch.deltaY
- else
- debugtouch[touch.id].motY = debugtouch[touch.id].motY * 0.9 + 0.1 * touch.deltaY
- end
- local rad = math.atan2(deb.motY, deb.motX)
- local deg = math.deg(rad)
- local offX, offY = math.cos(rad), math.sin(rad)
- debugtouch[touch.id].rad = rad
- debugtouch[touch.id].deg = deg
- debugtouch[touch.id].direction = vec2(offX, offY)
- still = inRange(deb.startX, deb.startY, 20, touch.x, touch.y) and math.abs(deb.motX) <= 15 and math.abs(deb.motY) <= 15
- if ElapsedTime - deb.start >= 0.8 then
- if still and not deb.long then
- if type(longPressed) == "function" then
- longPressed(touch, deb)
- debugtouch[touch.id].long = true
- end
- end
- end
- if deb.long then
- if type(longPressing) == "function" then
- longPressing(touch, deb)
- end
- end
- end
- if touch.state == ENDED or touch.state == CANCELLED then
- if still then
- if ElapsedTime - deb.start <= 0.3 then
- if type(tapped) == "function" then
- tapped(touch, deb)
- end
- end
- if ElapsedTime - deb.start >= 0.8 and not deb.long then
- if type(longPressed) == "function" then
- longPressed(touch, deb)
- debugtouch[touch.id].long = true
- end
- end
- end
- if deb.long then
- if type(longPressing) == "function" then
- longPressing(touch, deb)
- end
- end
- if ElapsedTime - deb.start <= 0.5 then
- if (not inRange(deb.startX, deb.startY, 10, touch.x, touch.y)) and (not (math.abs(deb.motX) + math.abs(deb.motY) <= 10)) then
- if type(swiped) == "function" then
- swiped({id = touch.id, x = touch.x, y = touch.y, startX = deb.startX, startY = deb.startY, motX = deb.motX, motY = deb.motY, rad = deb.rad, deg = deb.deg, direction = deb.direction }, deb)
- end
- end
- end
- nextf(function()
- touches[touch.id] = nil
- debugtouch[touch.id] = nil
- end)
- end
- if type(debtouched) == "function" then
- debtouched(debugtouch[touch.id])
- end
- end
- tween.delay(0, function()
- local _touched = touched or function() end
- touched = function(...)
- handle(...)
- _touched(...)
- end
- local _draw = draw or function() end
- draw = function(...)
- if Flickable.constant then
- for k, v in pairs(touches) do
- if v.state == BEGAN or v.state == MOVING then
- handle(v)
- end
- end
- end
- _draw(...)
- end
- end)
- --# Main
- -- Flickable
- --[[
- #### DOCUMENTATION ####
- ## API FEATURES ##
- # GLOBALS #
- Flickable: table:
- // Table for storing values to customize the Flickable API
- -angleOffset: number, offset of angles when using getNameFromAngle(...), getBoolFromAngle(...)
- -constant: boolean, whether to update touches every frame rather than when they move (recommended for detecting long presses moving)
- -useCorners: boolean, whether corners should be a possibility when using getNameFromAngle(...), getBoolFromAngle(...)
- # FUNCTIONS #
- getDebugFromID(id):
- //Get a debug value from a touch ID (see debtouched(deb))
- -id: number, ID of the touch
- getDebugFromTouch(touch):
- //Get a debug value from a touch (see debtouched(deb))
- -touch: default "touch" metatable
- getTouchFromID(id):
- //Get a default "touch" metatable from a debug value ID (see debtouched(deb))
- -id: number, ID of the debug value
- getTouchFromDebug(debug):
- //Get a default "touch" metatable from a debug value (see debtouched(deb))
- -debug: see debtouched(deb)
- getNameFromMotion(x, y, human):
- // Get the names of the direction of a motion (output order for corners: horizontal-vertical) (simpler, innaccurate)
- -x, y: numbers, x and y values of the motion
- -human: boolean, whether the output should be optimized for humans
- getNameFromAngle(angle, human):
- // Get the names of the direction of an angle (output order for corners: horizontal-vertical) (complicated, accurate)
- -angle: number, angle in degrees of the motion
- -human: boolean, whether the output should be optimized for humans
- getBoolFromMotion(x, y):
- // Returns a table of booleans {top, bottom, right, left}, each value determines whether the motion is moving in its direction (simpler, innaccurate)
- -x, y: numbers, x and y values of the motion
- getBoolFromAngle(angle):
- // Returns a table of booleans {top, bottom, right, left}, each value determines whether the angle is pointing in its direction (complicated, accurate)
- -angle: number, angle in degrees of the motion
- ## USER-DEFINED ##
- (parameters are supplied by Flickable)
- debtouched(deb):
- // Called alongside touched(touch), debug information
- -deb: table, contains debug information:
- --id: number, ID of the debug value/touch
- --start: number, ElapsedTime from when touch started
- --startX: number, X coordinate from when touch started
- --startY: number, Y coordinate from when touch started
- --motX: number, X motion of touch
- --motY: number, Y motion of touch
- --long: boolean, whether the touch had been deemed a long press
- tapped(tap, deb):
- // Called when a finger has tapped the screen
- -tap: default "touch" metatable
- -deb: see debtouched(deb)
- swiped(swipe, deb):
- // Called when a finger has swiped the screen
- -swipe: table, stores information about the swipe
- --id: number, ID of the touch
- --x: number, X position from when touch ended
- --y: number, Y position from when touch ended
- --startX: number, X position from when touch started
- --startY: number, Y position from when touch started
- --motX: number, X motion of touch
- --motY: number, Y motion of touch
- --rad: number, angle of the touch's direction in radians
- --deg: number, angle of the touch's direction in degrees
- --direction: vec2, UV version of motX and motY, sine/cosine of rad
- -deb: see debtouched(deb)
- longPressed(press, deb):
- // Called when a finger has long pressed the screen (on start of long press qualify)
- -press: default "touch" metatable
- -deb: see debtouched(deb)
- longPressing(press, deb):
- // Called when a touch qualified as a long press moves (or if Flickable.constant is true, every frame a touch qualified as long is on the screen), useful for long-press-to-move functionality, such as on the app screen of your iPad
- -press: default "touch" metatable
- -deb: see debtouched(deb)
- --]]
- rectMode(CENTER)
- -- Use this function to perform your initial setup
- function setup()
- print("Tap to make the cube bounce")
- print("Swipe to make the cube move (diagonally works too!)")
- print("Long press the cube to move it around")
- Flickable.constant = true
- --Flickable.useCorners = false
- gridSize = 8
- pos = {x = WIDTH / 2 + WIDTH / gridSize / 2, y = HEIGHT / 2 + HEIGHT / gridSize / 2}
- vis = {x = pos.x, y = pos.y}
- next = {x = pos.x, y = pos.y}
- size = {s = 1}
- img = image(512, 512)
- setContext(img)
- background(255)
- fill(0)
- font("ArialRoundedMTBold")
- fontSize(36)
- textMode(CORNER)
- text("Easy touch library\nBy SkyTheCoder", 8, 8)
- local w, h = textSize("Easy touch library\nBy SkyTheCoder")
- strokeWidth(2)
- stroke(0)
- line(0, h + 16, 512, h + 16)
- fontSize(72)
- textMode(CENTER)
- text("Flickable", 256, 256 + (h + 16) / 2)
- setContext()
- saveImage("Project:Icon", img)
- end
- -- This function gets called once every frame
- function draw()
- background(255)
- stroke(0)
- strokeWidth(1)
- for i = 1, gridSize - 1 do
- line(0, i / gridSize * HEIGHT, WIDTH, i / gridSize * HEIGHT)
- end
- for i = 1, gridSize - 1 do
- line(i / gridSize * WIDTH, 0, i / gridSize * WIDTH, HEIGHT)
- end
- pushMatrix()
- --translate(vis.x + WIDTH / gridSize / 2, vis.y + HEIGHT / gridSize / 2)
- translate(vis.x, vis.y)
- scale(size.s)
- noStroke()
- fill(0)
- rect(0, 0, WIDTH / gridSize, HEIGHT / gridSize)
- fill(255)
- font("ArialRoundedMTBold")
- fontSize(12)
- text("Flickable")
- popMatrix()
- tint(255, 255 - (ElapsedTime - 4) * 127)
- sprite(img, WIDTH / 2, HEIGHT / 2)
- end
- function swiped(swipe)
- --print("Swiped: " .. swipe.x .. ", " .. swipe.y)
- print("Swiped " .. getNameFromAngle(swipe.deg, true))
- if tPos ~= nil then
- tween.stop(tPos)
- pos.x = next.x
- pos.y = next.y
- vis.x = pos.x
- vis.y = pos.y
- tPos = nil
- end
- local bools = getBoolFromAngle(swipe.deg)
- local target = {x = pos.x, y = pos.y}
- if bools.up then
- target.y = pos.y + HEIGHT / gridSize
- end
- if bools.down then
- target.y = pos.y - HEIGHT / gridSize
- end
- if bools.right then
- target.x = pos.x + WIDTH / gridSize
- end
- if bools.left then
- target.x = pos.x - WIDTH / gridSize
- end
- --[[target.x = target.x or pos.x
- target.y = target.y or pos.y--]]
- next.x = target.x
- next.y = target.y
- tPos = tween(0.25, vis, target, tween.easing.quadIn, function()
- pos.x, pos.y = vis.x, vis.y
- tPos = nil
- end)
- end
- function tapped(tap)
- if tSize ~= nil then
- tween.stop(tSize)
- tSize = nil
- size = {s = 1}
- end
- tSize = tween(0.15, size, {s = 0.75}, tween.easing.quadInOut, function()
- tSize = tween(0.5, size, {s = 1}, tween.easing.elasticOut, function()
- tSize = nil
- end)
- end)
- end
- function longPressed(press)
- vis.x, vis.y = press.x, press.y
- if tSize ~= nil then
- tween.stop(tSize)
- tSize = nil
- size = {s = 1}
- end
- tSize = tween(0.5, size, {s = 1.25}, tween.easing.bounceOut, function()
- tSize = nil
- end)
- end
- function longPressing(press)
- if tPos ~= nil then
- tween.stop(tPos)
- tPos = nil
- end
- vis.x, vis.y = press.x, press.y
- next.x = math.floor(vis.x / WIDTH * gridSize) * WIDTH / gridSize + WIDTH / gridSize / 2
- next.y = math.floor(vis.y / HEIGHT * gridSize) * HEIGHT / gridSize + HEIGHT / gridSize / 2
- if press.state == ENDED or press.state == CANCELLED then
- if tSize ~= nil then
- tween.stop(tSize)
- tSize = nil
- size = {s = 1.25}
- end
- tSize = tween(0.5, size, {s = 1}, tween.easing.elasticOut, function()
- tSize = nil
- end)
- tPos = tween(0.25, vis, next, tween.easing.quadIn, function()
- pos.x, pos.y = vis.x, vis.y
- tPos = nil
- end)
- end
- end
- --[[function debtouched(deb)
- for k, v in pairs(deb) do
- if type(v) ~= "userdata" then
- print(k .. ": " .. tostring(v))
- end
- end
- end--]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement