Swiping an object to fixed points is not response in good way

i am using this tut to Swiping an object to fixed points .

https://coronalabs.com/blog/2014/09/16/tutorial-swiping-an-object-to-fixed-points/

i am not using the transition.to() due to physics and instead i am using setLinearVelocity

the object size is 30x30

when i try to swipe that object lots of time it didn’t move . no response and i have to try so many times touching the object and try to swipe it and  make the object move . i tried it in more than one phone/tablet Android

here is my code so far

local LEFT = 50 local CENTER = display.contentCenterX local RIGHT = display.contentWidth - 50 local UpMove = 50 local CENTERY = display.contentCenterY local DownMove = display.contentHeight - 50 local function handleSwipeX( event ) if event.phase == "moved" then local dX = event.x - event.xStart if dX \> 15 then -- swipe right local spot = RIGHT if event.target.x == LEFT then spot = CENTER end event.target:setLinearVelocity(400,0) elseif dX \< -15 then -- swipe left local spot = LEFT if event.target.x == RIGHT then spot = CENTER end event.target:setLinearVelocity(-400,0) end end return true end

Hi @sobh,

There seems to be ongoing confusion about physics and transitions, so I recently added some details and notes to the following page. You should read it to clarify how these two aspects actually can work in conjunction, if handled properly.

https://docs.coronalabs.com/guide/physics/limitations/index.html

Best regards,

Brent

Thanks @Brent Sorrentino

i am not using transitions , instead i am using setLinearVelocity and fixed rotation .and it works as i want .

but as i mention in the post the issue now that the response for the swipe itself is not in timely fashion . i have to (touch) and try to move the object so many times till it start moving . however when i enable joint for that object it immediately response to my touch .

but i dont want to enable joints because it make object swipe and move in random position ( according to where exactly you touched due to joints )

so how can i fix that swipe response issue ?

btw my player character is just a stone or a brick that just needed to be moved to x or y ( just like stone in mazes )

i see some x velocity, i don’t what your gravity is, and what the friction is or density. You may have to play with the physics to get is working for you. Touch joints are the really world equivalent of grabbing an object, while setLinearVelocity() is the equivalent of push an object. 

​I would aiso try using apply linear impuse or apply force 

Hi @sobh,

Aside from how you’re moving it, I think you should implement better touch handling. You should set focus on the object when it first receives touch, so that nothing else potentially grabs touch events. Then, when you decide that a “successful swipe” has occurred, you should consider setting a boolean property on the object which tells Corona/Lua that the object will start moving, and that it should stop processing “moved” events beyond that point (remember, you get dozens or even hundreds of “moved” events as you drag across an object, depending on its size).

Take care,

Brent

hi @scottrules44

well i am just trying to move the player on the X so no need for Y

there are no gravity . i set it to 0 in both x and y

i tried all physics parameter and it is nothing to do with it .

the point is seems to be that most of the time the touch event is not even fired .

@Brent Sorrentino

i will check the setFocus and will update here

i am using this code now

local LEFT = 50 local CENTER = display.contentCenterX local RIGHT = display.contentWidth - 50 local UpMove = 50 local CENTERY = display.contentCenterY local DownMove = display.contentHeight - 50 local function handleSwipeX( event ) if event.phase == "moved" then local dX = event.x - event.xStart if dX \> 5 then -- swipe right local spot = RIGHT if event.target.x == LEFT then spot = CENTER end event.target:setLinearVelocity(1400,0) event.target:applyLinearImpulse(100,0) elseif dX \< -5 then -- swipe left local spot = LEFT if event.target.x == RIGHT then spot = CENTER end --event.target:setLinearVelocity(-1400,0) event.target:applyLinearImpulse(-100,0) end end return true end local function handleSwipeY( event ) if event.phase == "moved" then local dY = event.y - event.yStart if dY \> 5 then -- swipe right local spotY = DownMove if event.target.Y == UpMove then spot = CENTERY end --event.target:setLinearVelocity(0,1400) event.target:applyLinearImpulse(0,100) elseif dY \< -5 then -- swipe left local spotY = UpMove if event.target.Y == DownMove then spot = CENTERY end event.target:applyLinearImpulse(0,-100) --event.target:setLinearVelocity(0,-1400) end end return true end

the applyLinearImpulse seems fixed the repose issue . but now i have another issue related to the swipe .

i need to swipe the object only on the X and Y ( horizontally or vertically only ) . but using the above code will swipe the object from the swipe start point to the swipe end point wherever if it is diagonal or horizontally or vertically

for example if i swipe my finger from x.0-y0 to x.100-y100  it will move in diagonal to that point  and i need to prevent that . i need only to allow object and swipe to  move along horizontally or vertically only . so in the above example i dont want to allow the object to move . instead i have to swipe from x0-y0  to x0-y100

how can i do that ?

Hi @sobh,

Well, you can’t really control how the user swipes, but you can control how to handle that swipe. I suggest making a comparison of both the Y delta (what you’ve done with “dY”) and also the X delta. Then, you can basically “filter out” swipes that are too far away from the strict up/down or left/right by axes.

For example, let’s say the user swipes basically up, but slightly diagonally to the right as well. The “dY < -5” condition will be triggered first, at which point you can also check “is dX > -2 and dX < 2”? If not, then ignore the swipe entirely, because the user has swiped too much in a diagonal direction. Note that -2 and 2 here are just my examples, not anything specifc… you could make your dX range [-4,4], [-3,3], [-1,1], etc.

Hope that makes sense… I may not have described it very well. :stuck_out_tongue:

Brent

Thanks@Brent

yes i got you . but that way will not solve one major move . which is direct diagonal swipe . your suggested way will only fix the player swipe first up then swipe to the right of the left . but if the player from the start swipe diagonally then the object will move in diagonal way .

is there is any one to force the object to be moved in horizontally or vertically only…

i guess even if i used transition will not help …i just dont want to use normal axis to move that stone . swipe objects are more easy and fun .  i might use very low alpha axis which jointed around the stone and player move it by pressing that axis .

what do you think what is the best way to do it ?>

can we find a way to swipe as our needs ?

Hi @sobh,

What behavior do you want when the user swipes diagonally? And by “diagonally”, how much variance will you allow? If the user swipes at 45, 135, 225, or 315 degrees, will you allow that or is it too diagonal?

My suggestion can definitely be used to filter out diagonal swipes, up to a certain threshold, and then apply either horizontal or vertical force to the object (but not both at the same time which would make it move diagonally).

Best regards,

Brent

i want the object to move only to 90 degree . like rock in chess :slight_smile:

i found this topic

http://stackoverflow.com/questions/18129421/how-to-find-the-angle-when-finger-is-swiped-over-an-object-in-corona

i guess i can use it to do what i want .

any idea ?

I just fixed it using a simple way

local function handleSwipeX( event ) if event.phase == "moved" then -- display.getCurrentStage():setFocus(event.target) local dX = event.x - event.xStart if dX \> 5 and event.yStart == event.y then -- swipe right local spot = RIGHT if event.target.x == LEFT then spot = CENTER end --event.target:setLinearVelocity(1400,0) event.target:applyLinearImpulse(10000,0) elseif dX \< -5 then -- swipe left local spot = LEFT if event.target.x == RIGHT then spot = CENTER end --event.target:setLinearVelocity(-1400,0) event.target:applyLinearImpulse(-10000,0) end end return true end local function handleSwipeY( event ) if event.phase == "moved" then print(event.x) -- display.getCurrentStage():setFocus(event.target) local dY = event.y - event.yStart if dY \> 5 and event.xStart == event.x then -- swipe right local spotY = DownMove if event.target.Y == UpMove then print(event.x) spot = CENTERY end --event.target:setLinearVelocity(0,1400) event.target:applyLinearImpulse(0,10000) elseif dY \< -5 then -- swipe left local spotY = UpMove if event.target.Y == DownMove then spot = CENTERY end -- event.target:applyLinearImpulse(0,-100) event.target:setLinearVelocity(0,-10000) end end return true end

just by comparing event.yStart == event.y and event.xStart == event.x

My concern with this is, will the user ever trigger these conditions? Imagine the user’s touch begins at x=50, and he/she starts to swipe down. As that happens, the x position of the touch (event.x) will vary considerably: it could sway between 45 and 55, and it might even end up being decimal values. So, it’s very unlikely that, at any point, the x position will be exactly 50 again. So, your condition will rarely occur.

Your approach is pretty close, but I would suggest giving the user a little flexibility like this (example in your “handleSwipeY()” function):

[lua]

if dY > 5 and ( event.x >= event.xStart-2 and event.x <= event.xStart+2 ) then

[/lua]

I would also recommend that you combine these two functions into one. It’s easy enough… just do a 4-condition “if-elseif-elseif-elseif” block.

Take care,

Brent

Thanks @ Brent 

yes this made it a little uncomfortable for users ( trying to swipe more than once to make it work )

i was thinking of posting new topic about this issue .

see when i use touch Joy Stick ( Axis ) ( up,down,left,right) my object can move in vertical or horizontally without any problem . but once i use swipe to push or swipe the object , lots of time the object move in angles which is not what i want …

The Game i am making is simply like chess without the grids . and it have one piece act as player which is just a square  stone .

i want to push that square stone till it reach its finish place in only vertical or horizontal ways . , i can accomplish this without any problem using the ( Axis ) ( up,down,left,right) drawn in the corner of the game . but it is not fun to use it like this… and when i swipe of push the squre stone it most of the time go in strange directions ( i already enabled fixedRoation ) which didnot helo

Hi @sobh,

I whipped up the following code for you. I think it accomplishes the basics of what you need. Of course there can be minor enhancements made, but that’s up to you. :slight_smile:

[lua]

local rock = display.newCircle( display.contentCenterX, display.contentCenterY, 25 )

rock.canBeSwiped = true

local function doSwipe( event )

   if ( event.phase == “began” ) then

      display.getCurrentStage():setFocus( event.target )

   elseif ( event.phase == “moved” ) then

      if ( rock.canBeSwiped == false ) then return end

      local dX = event.x - event.xStart

      local dY = event.y - event.yStart

      if dY > 5 and ( dX >= -2 and dX <= 2 ) then  – Down!

         rock.canBeSwiped = false

         transition.to( rock, { y=rock.y+50, transition=easing.outQuad,

            onComplete=function() rock.canBeSwiped = true end } )

      elseif dY < -5 and ( dX >= -2 and dX <= 2 ) then  – Up!

         rock.canBeSwiped = false

         transition.to( rock, { y=rock.y-50, transition=easing.outQuad,

            onComplete=function() rock.canBeSwiped = true end } )

      elseif dX < -5 and ( dY >= -2 and dY <= 2 ) then  – Left!

         rock.canBeSwiped = false

         transition.to( rock, { x=rock.x-50, transition=easing.outQuad,

            onComplete=function() rock.canBeSwiped = true end } )

      elseif dX > 5 and ( dY >= -2 and dY <= 2 ) then  – Right!

         rock.canBeSwiped = false

         transition.to( rock, { x=rock.x+50, transition=easing.outQuad,

            onComplete=function() rock.canBeSwiped = true end } )

      end

   elseif ( event.phase == “ended” or event.phase == “cancelled” ) then

      display.getCurrentStage():setFocus( nil )

      print(“FOCUS RELEASED”)

   end

end

rock:addEventListener( “touch”, doSwipe )

[/lua]

Thanks Brent but i tried Transition before and it didnot work with physics as i expected .

ok :slight_smile: i will give you more hint about my game .

that stone ( square ) have to stop if it collide with another stone ( square ) and when i used transition it didnot do that before . that why i used other ways like applyLinearImpulse

i already tried your code now . and collision didn’t fire .

if we can find a way to use easing with force i think will very much help

You can continue using linear impulse if you want, by applying strictly up, down, left, or right impulse in place of the associated transitions I used. Just remember that impulse “builds up” so you should reset the object’s linear velocity each time you make a new swipe:

[lua]

rock:setLinearVelocity( 0, 0 )

[/lua]

And, you can still use transitions if you want, but you’ll need to follow the advice shown here:

https://docs.coronalabs.com/guide/physics/limitations/index.html

Brent

As for making the object gradually slow down when using force (as in, it slowly comes to a stop), you can apply linear damping to it:

https://docs.coronalabs.com/api/type/Body/linearDamping.html

local physics = require("physics") physics.start( ) physics.setGravity( 0, 0 ) local rock = display.newCircle( display.contentCenterX, display.contentCenterY, 25 ) rock.canBeSwiped = true physics.addBody( rock, "dynamic" ) rock.linearDamping = .5 local function doSwipe( event ) if ( event.phase == "began" ) then display.getCurrentStage():setFocus( event.target ) elseif ( event.phase == "moved" ) then if ( rock.canBeSwiped == false ) then return end local dX = event.x - event.xStart local dY = event.y - event.yStart if dY \> 5 and ( dX \>= -2 and dX \<= 2 ) then -- Down! rock.canBeSwiped = false rock:setLinearVelocity( 0, 50 ) rock.canBeSwiped = true elseif dY \< -5 and ( dX \>= -2 and dX \<= 2 ) then -- Up! rock.canBeSwiped = false rock:setLinearVelocity( 0, -50 ) rock.canBeSwiped = true elseif dX \< -5 and ( dY \>= -2 and dY \<= 2 ) then -- Left! rock.canBeSwiped = false rock:setLinearVelocity( -50, 0 ) rock.canBeSwiped = true elseif dX \> 5 and ( dY \>= -2 and dY \<= 2 ) then -- Right! rock.canBeSwiped = false rock:setLinearVelocity( 50, 0 ) rock.canBeSwiped = true end elseif ( event.phase == "ended" or event.phase == "cancelled" ) then display.getCurrentStage():setFocus( nil ) print("FOCUS RELEASED") end end rock:addEventListener( "touch", doSwipe )

Thanks Both . but none of this made any difference .

using touch ( swipe ) along with applyForce or setLinearVelocity or any other forces make the movement of the object pretty unstable in some points ( i mean it will not make the object all the time go in vertical or horizontally )  . i guess it happen when you hit to touch the object from different angles or corners of the square that make the square move in different ways according to where the square had been touched  .

but in the other hand when i use Axis ( just Up,down,left,right ) arrows and apply those forces or to setLinearVelocity  the object ( square ) can move very steady without any change in its direction

but putting Axis in a puzzle game for mobile is not emotional

btw i tried many things like changing physics parameter , linear Dumping etc, the size of the square is 32*32