120 lines
3.5 KiB
Plaintext
120 lines
3.5 KiB
Plaintext
var time = use('time')
|
|
var audio = use('sound')
|
|
var math = use('math/radians')
|
|
|
|
var gesture = {}
|
|
|
|
gesture.MIN_SWIPE = 30
|
|
gesture.MAX_TIME = 500
|
|
gesture.PINCH_TH = 10
|
|
|
|
gesture.reset = function() {
|
|
this.touches = {} // Track active touches by finger id
|
|
this.gestureState = null // Current gesture being tracked
|
|
this.startTime = 0
|
|
this.startDist = 0
|
|
}
|
|
|
|
gesture.on_input = function(action_id, action) {
|
|
if (search(action_id, 'gamepad_touchpad_') == null) return
|
|
|
|
var finger = action.finger || 0
|
|
var touchpad = action.touchpad || 0
|
|
var fingerId = `${touchpad}_${finger}`
|
|
|
|
if (action_id == 'gamepad_touchpad_down') {
|
|
// Add new touch
|
|
this.touches[fingerId] = {
|
|
x: action.x,
|
|
y: action.y,
|
|
startX: action.x,
|
|
startY: action.y,
|
|
startTime: time.number()
|
|
}
|
|
|
|
var touchCount = length(array(this.touches))
|
|
|
|
if (touchCount == 1) {
|
|
// Single touch started
|
|
this.gestureState = 'single'
|
|
this.startTime = time.number()
|
|
} else if (touchCount == 2) {
|
|
// Two touches - potential pinch
|
|
this.gestureState = 'multi'
|
|
var fingers = array(array(this.touches), k => this.touches[k])
|
|
this.startDist = this.dist(fingers[0], fingers[1])
|
|
}
|
|
}
|
|
else if (action_id == 'gamepad_touchpad_motion') {
|
|
if (this.touches[fingerId]) {
|
|
// Update touch position
|
|
this.touches[fingerId].x = action.x
|
|
this.touches[fingerId].y = action.y
|
|
|
|
var touchCount = length(array(this.touches))
|
|
|
|
if (touchCount == 2 && this.gestureState == 'multi') {
|
|
// Check for pinch gesture
|
|
var fingers = array(array(this.touches), k => this.touches[k])
|
|
var currentDist = this.dist(fingers[0], fingers[1])
|
|
var d = currentDist - this.startDist
|
|
|
|
if (abs(d) >= this.PINCH_TH) {
|
|
var gesture_type = d > 0 ? 'pinch_out' : 'pinch_in'
|
|
// scene.recurse(game.root, 'on_input', [gesture_type, { delta: d }])
|
|
this.startDist = currentDist
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (action_id == 'gamepad_touchpad_up') {
|
|
if (this.touches[fingerId]) {
|
|
var touch = this.touches[fingerId]
|
|
var touchCount = length(array(this.touches))
|
|
|
|
// Check for swipe if this was the only/last touch
|
|
if (touchCount == 1 && this.gestureState == 'single') {
|
|
var dt = time.number() - touch.startTime
|
|
var dx = action.x - touch.startX
|
|
var dy = action.y - touch.startY
|
|
|
|
if (dt < this.MAX_TIME / 1000) { // Convert to seconds
|
|
var absX = abs(dx), absY = abs(dy)
|
|
if (absX > this.MIN_SWIPE / 100 || absY > this.MIN_SWIPE / 100) { // Normalize for 0-1 range
|
|
var dir = absX > absY
|
|
? (dx > 0 ? 'swipe_right' : 'swipe_left')
|
|
: (dy > 0 ? 'swipe_down' : 'swipe_up')
|
|
audio.play('swipe')
|
|
// scene.recurse(game.root, 'on_input', [dir, {pressed:true}])
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove touch
|
|
delete this.touches[fingerId]
|
|
|
|
// Reset if no touches left
|
|
if (length(array(this.touches)) == 0) {
|
|
this.gestureState = null
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
gesture.dist = function(p1, p2) {
|
|
var dx = p2.x - p1.x
|
|
var dy = p2.y - p1.y
|
|
return math.sqrt(math.power(dx, 2) + math.power(dy, 2))
|
|
}
|
|
|
|
|
|
return function(options) {
|
|
var obj = meme(gesture)
|
|
if (options) {
|
|
obj.MIN_SWIPE = options.minSwipe || gesture.MIN_SWIPE
|
|
obj.MAX_TIME = options.maxTime || gesture.MAX_TIME
|
|
obj.PINCH_TH = options.pinchThreshold || gesture.PINCH_TH
|
|
}
|
|
obj.reset()
|
|
return obj
|
|
} |