Can't get my swipe method to work correctly
Monkey Forums/Monkey Programming/Can't get my swipe method to work correctly
| ||
I'm trying to make a swipe method but I'm having a little trouble with it.'********************************** '** Check Swipe '********************************** Method CheckSwipe:Int() Local result:Int = 0 If touching = 0 And TouchDown(0) = 1 Then touching = 1 touchingXstart = TouchX() touchingYstart = TouchY() End If TouchDown(0) = 0 And touching = 1 Then touching = 0 touchingXend = TouchX() touchingYend = TouchY() If touchingXend > touchingXstart Then result = 1 If touchingXend < touchingXstart Then result = 3 If touchingYend > touchingYstart Then result = 2 If touchingYend < touchingYstart Then result = 4 touchingXstart = 0 touchingXend = 0 touchingYstart = 0 touchingYend = 0 End Return result End The touching variables are defined as Integers. I then call it like this in OnUpdate. swipeResult = CheckSwipe() I want the swipeResult to give this results. 1 = swipe right 2 = swipe down 3 = swipe left 4 = swipe up. BUT I can't get it working, any one got any idea on how to solve this? |
| ||
The results are overwriting each other because of the way you setup the if statements. If start x is less than end x, but then if start y is less than end y as well, the result is 2, even if you were aiming 1. |
| ||
Okay tried it differently but still not working.'********************************** '** Check Swipe '********************************** Method CheckSwipe:Int() Local result:Int = 0 If touching = 0 And TouchDown(0) = 1 Then touching = 1 touchingXstart = TouchX() touchingYstart = TouchY() End If TouchDown(0) = 0 And touching = 1 Then touching = 0 touchingXend = TouchX() touchingYend = TouchY() If touchingXend > touchingXstart Then touchingXstart = 0 touchingXend = 0 touchingYstart = 0 touchingYend = 0 Return 1 End If touchingXend < touchingXstart Then touchingXstart = 0 touchingXend = 0 touchingYstart = 0 touchingYend = 0 result = 3 End If touchingYend > touchingYstart Then touchingXstart = 0 touchingXend = 0 touchingYstart = 0 touchingYend = 0 result = 2 End If touchingYend < touchingYstart Then touchingXstart = 0 touchingXend = 0 touchingYstart = 0 touchingYend = 0 result = 4 End End Return result End |
| ||
Try this [monkeycode] Method CheckSwipe:Int() If Not touching And TouchDown(0) Then touching = True touchingXstart = TouchX() touchingYstart = TouchY() ElseIf Not TouchDown(0) And touching Then touching = False touchingXend = TouchX() touchingYend = TouchY() Local xDiff:Int = Max(touchingXend, touchingXstart) - Min(touchingXstart, touchingXend) Local yDiff:Int = Max(touchingYend, touchingYstart) - Min(touchingYstart, touchingYend) If xDiff > yDiff If touchingXend > touchingXstart Then Return 1 If touchingXend < touchingXstart Then Return 3 Else If touchingYend > touchingYstart Then Return 2 If touchingYend < touchingYstart Then Return 4 End End Return 0 End [/monkeycode] |
| ||
Sorry but your code doesn't seem to work for me. I checking like this in OnUpdate If CheckSwipe() = 1 Then score = 1 If CheckSwipe() = 2 Then score = 2 If CheckSwipe() = 3 Then score = 3 If CheckSwipe() = 4 Then score = 4 I'm drawing the value to screen but I dod not get the correct result. I only get a 1 return. |
| ||
The subsequent calls to CheckSwipe won't work, what do you get if you do the following...Local checkResult:int = CheckSwipe() If checkResult > 0 Print checkResult End |
| ||
Thats it! Thanks both of you now the swipe function works. |
| ||
I just quickly knocked this up, it allows for the screen to rotate but still detect up/left/right/down (relative to the rotation). It also has an optional tolerance value, allowing you to fine tune what should be recognised.Import mojo Const SWIPE_NONE : Int = 0 Const SWIPE_UP : Int = 1 Const SWIPE_DOWN : Int = 2 Const SWIPE_LEFT : Int = 3 Const SWIPE_RIGHT : Int = 4 '/ Screen Angle (allows swiping with rotation) Global AxisAngle : Float = 0.0 Class MyApp Extends App Field touchStart : Int[ 2 ] Field touchEnd : Int[ 2 ] Field touching : Bool Method OnCreate() SetUpdateRate 60 End Method Method OnUpdate() If KeyDown( KEY_LEFT ) Then AxisAngle = AxisAngle - 1.0 If KeyDown( KEY_RIGHT ) Then AxisAngle = AxisAngle + 1.0 If TouchDown() = 1 If touching = False touching = True touchStart[ 0 ] = TouchX() touchStart[ 1 ] = TouchY() Else touchEnd[ 0 ] = TouchX() touchEnd[ 1 ] = TouchY() Endif Else If touching = True '/ check if touch vector is a valid swip Local result : Int = GestureSwipe( touchStart, touchEnd ) If result = SWIPE_NONE Then Print "Not a valid swipe" If result = SWIPE_UP Then Print "Swipe Up Detected!" If result = SWIPE_DOWN Then Print "Swipe Down Detected!" If result = SWIPE_LEFT Then Print "Swipe Left Detected!" If result = SWIPE_RIGHT Then Print "Swipe Right Detected!" touching = False Endif Endif End Method Method OnRender() Cls 0, 0, 0 DrawText "Press Left / Right to rotate Axis", 0, 0 Local centreX : Int = DeviceWidth() / 2 Local centreY : Int = DeviceHeight() / 2 DrawLine centreX, centreY, centreX + Cos( AxisAngle ) * 100, centreY + Sin( AxisAngle ) * 100 DrawLine centreX, centreY, centreX + Sin( AxisAngle ) * 100, centreY - Cos( AxisAngle ) * 100 End Method End Class Function Main() New MyApp() End Function Function GestureSwipe : Int( touchStart : Int[], touchEnd : Int[], tolerance : Float = 0.15 ) Local touchVectorX : Float = touchEnd[ 0 ] - touchStart[ 0 ] Local touchVectorY : Float = touchEnd[ 1 ] - touchStart[ 1 ] Local touchLength : Float = Sqrt( touchVectorX * touchVectorX + touchVectorY * touchVectorY ) touchVectorX = touchVectorX / touchLength touchVectorY = touchVectorY / touchLength Local dot : Float = touchVectorX * Cos( AxisAngle ) + touchVectorY * Sin( AxisAngle ) If Abs( dot ) < tolerance If touchVectorY < 0 Then Return SWIPE_UP Return SWIPE_DOWN Endif If Abs( dot ) > 1.0 - tolerance If touchVectorX < 0 Then Return SWIPE_LEFT Return SWIPE_RIGHT Endif Return SWIPE_NONE End Function |
| ||
Thats some nice piece of code NoOdle. Could come in handy! |
| ||
This is definitely hacky, but I extended NoOdle's code with detection of a few more gestures, some basic inertia, etc. New stuff: * I moved GestureSwipe() and the update stuff into a class; all you should need to do is create an instance of NoodleSwipe and check Local result:Int = swipeMon.Update() * it can now return while drags are in progress, including if the drag changes direction midway * it also returns inertia values (a decaying float; change NoodleSwipe.inertiaDamp to affect the damping rate) * it maintains a history of the drag, might be useful for drawing paths or lines or detecting arcs. You can get segment lengths and durations out, etc. * there's a bunch of new helper methods in there. |
| ||
Updated the above with a fix for drags, much nicer inertia, plus added more visualization to the test app. |
| ||
Look great! could you show the use of 'Inertia' in your next update test. |
| ||
It's pretty simple, and the test class does show how it works. If you run this in HTML5 you can see the inertia events firing in the text box, and see how it decays away. How I am using it in my game right now (pseudocode): Be sure to adjust the inertiaDamp value to suit your use case. I defaulted it at 0.9, but that was too many inertia ticks for the particular usage I had. I then tried 0.5, and it died off too fast. Currently at 0.75, may move it to 0.8! Same with dragRange. The default is 50. Probably want to adjust it based on screen and device size. 44px at non-retina levels is what Apple recommends for a touch, but of course, you go retina and it goes to 100, Android has a pile of resolutions and screen sizes, etc. Also, cf this bug report here: http://www.monkeycoder.co.nz/Community/posts.php?topic=5645 If you add this one-line hack: you'll get consistent behavior across platforms. |
| ||
I use ATAN2 with my swipes, then from the angle I can see if it's up,down,left or right. And then Sqrt to find the distance.Class TouchSwip Field originX:Int Field originY:Int Field distanceFromOrigin:Int Field angle:Int Field isTouched:Bool Field state:Int Field nullZoneDistance:Int Field direction:Int Method New(tMinDistance:Int) nullZoneDistance = tMinDistance End Method Method Render() If state <> 2 Then Return DrawLine originX - nullZoneDistance, originY - nullZoneDistance, originX + nullZoneDistance, originY + nullZoneDistance DrawLine originX + nullZoneDistance, originY - nullZoneDistance, originX - nullZoneDistance, originY + nullZoneDistance End Method Method Update() Local x:Int = TouchX Local y:Int = TouchY Select state Case 0 If isTouched = False And TouchDown(0) = True Then state = 1 Case 1 isTouched = True state = 2 originX = TouchX originY = TouchY Case 2 Local x:Int = TouchX Local y:Int = TouchY If TouchDown(0) = True distanceFromOrigin = Sqrt( (x - originX) * (x - originX) + (y - originY) * (y - originY)) angle = (ATan2(originX - x, originY - y) + (180)) / 45 Else If distanceFromOrigin > nullZoneDistance If angle = 4 or angle = 3 Then direction = 0 If angle = 2 or angle = 1 Then direction = 1 If angle = 7 or angle = 0 Then direction = 2 If angle = 5 or angle = 6 Then direction = 3 Else Self.Clear End If End If End Select End Method Method Clear() isTouched = False angle = -1 direction = -1 state = 0 End Method Method Up:Bool() If direction = 0 Then Self.Clear; Return True Return False End Method Method Right:Bool() If direction = 1 Then Self.Clear; Return True Return False End Method Method Down:Bool() If direction = 2 Then Self.Clear; Return True Return False End Method Method Left:Bool() If direction = 3 Then Self.Clear; Return True Return False End Method End Class |