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

If you’re applying force (not setting linear velocity directly as @scottrules44 showed) then you’ll need to reset the object’s linear velocity to 0,0 on each new swipe. Otherwise, the force will build up and the object will go off in different angles.

Also, in @scottrules44 code, the “rock.canBeSwiped = true” command should probably not be done in each conditional block, because that could easily result in force being applied multiple times during the swiping motion. Instead, try putting that command just once in the “ended”/“cancelled” condition area, so that the user can’t make another swipe in any direction until he/she has lifted off the screen.

Brent

Which exact API are you using to move the object at this time? It appears you don’t want to use transitions, and that’s OK, but I need to see what you’re doing now in your own code…

here is my code .

--------------------------------------------------------------------------------- -- -- scene.lua -- --------------------------------------------------------------------------------- local sceneName = ... local composer = require( "composer" ) local json = require( "json" ) local loadsave = require( "loadsave" ) local myData = require( "mydata" ) local physics = require("physics") -- Load scene with same root filename as this file local scene = composer.newScene( sceneName ) --------------------------------------------------------------------------------- centerX = display.contentCenterX centerY = display.contentCenterY screenLeft = display.screenOriginX screenWidth = display.contentWidth - screenLeft \* 2 screenRight = screenLeft + screenWidth screenTop = display.screenOriginY screenHeight = display.contentHeight - screenTop \* 2 screenBottom = screenTop + screenHeight display.contentWidth = screenWidth display.contentHeight = screenHeight function scene:create( event ) local sceneGroup = self.view -- Called when the scene's view does not exist -- -- INSERT code here to initialize the scene -- e.g. add display objects to 'sceneGroup', add touch listeners, etc myData.settings = loadsave.loadTable( "settings.json" ) local pl2 = self:getObjectByName( "pl2" ) local bk = self:getObjectByName( "bk" ) BaseT = self:getObjectByName( "BaseT" ) local borderDown = self:getObjectByName( "borderDown" ) local borderUp = self:getObjectByName( "borderUp" ) local borderLeft= self:getObjectByName( "borderLeft" ) local borderRight = self:getObjectByName( "borderRight" ) borderDown.name="borderDown" borderUp.name="borderUp" borderLeft.name="borderLeft" borderRight.name="borderRight" borderDown.name="borderDown" pl2.name="pl2" BaseT.name="BaseT" --physics.setDrawMode( "hybrid" ) --physics.setDrawMode( "debug" ) local CoronaDev = display.newText( "Level 2",25,25, "Exo-ExtraLight.otf", 13 ) CoronaDev.x=30 CoronaDev.y=-20 sceneGroup:insert(CoronaDev) CoronaDev:setTextColor( 0.5,0.5,0.5 ) ---New Move With Tweaks --- local function handleSwipe( event ) if ( event.phase == "began" ) then -- display.getCurrentStage():setFocus( event.target ) -- This made object stop moving once the swipe stop in fast way elseif ( event.phase == "moved" ) then local dX = event.x - event.xStart local dY = event.y - event.yStart if event.phase == "moved" then if dX \>= 10 then event.target:setLinearVelocity(600,0) elseif dX \<= -10 then event.target:setLinearVelocity(-600,0) elseif dY \>= 10 then event.target:setLinearVelocity(0,600) elseif dY \<= -10 then event.target:applyLinearImpulse(0,-600) end end return true elseif ( event.phase == "ended" or event.phase == "cancelled" ) then --event.target:setLinearVelocity(0,0) --- This put strange stop if the touch was so short end end local SaveLevel = function () myData.settings.currentLevel = 2 end SaveLevel() local GoToNextLevel = function ( event ) if ( event.phase == "began" ) then if event.target.name == "BaseT" then Level=2 composer.showOverlay( "pass") pl2:setLinearVelocity(0,0) myData.settings.unlockedLevels = 3 end end end local SquareGoAway = function ( event ) if ( event.phase == "began" ) then if event.target.name == "borderDown" or event.target.name == "borderUp" or event.target.name == "borderLeft" or event.target.name == "borderRight" or event.target.name == "borderRightDown"then local GameOver=1 composer.gotoScene ("GameOver") return true end end end local SoundImpact = function ( event ) if ( event.phase == "began" ) then SoundImpactName = audio.play (SoundImpact,{ channel=3}) pl2:setLinearVelocity(0,0) return true elseif ( event.phase == "ended" ) then end return true end borderRight:addEventListener( "collision", SquareGoAway ) borderUp:addEventListener( "collision", SquareGoAway ) borderLeft:addEventListener( "collision", SquareGoAway ) borderDown:addEventListener( "collision", SquareGoAway ) BaseT:addEventListener( "collision", GoToNextLevel ) pl2:addEventListener( "touch", handleSwipe ) pl2:addEventListener( "collision", SoundImpact ) Runtime:addEventListener( "enterFrame", SaveLevel ) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase loadsave.saveTable( myData.settings, "settings.json" ) end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc --BaseT:removeEventListener( "collision", GoToNextLevel ) end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

i removed the ( dX >= -2 and dX <= 2 ) and stuff becuase it made the swipe hard to complete .

pl2 is the square ( dynamic , Fixed Rotation , Active , Awake , Sleeping Allowed , 0 Angular Damping and 0 linear Damping , 0 bounce , 100 Friction , 20 Density , 0 Radius )

Other objects ( other Squares ) ( Static , Active , Friction 100 , bounce 0 , linear and angular damping are 0 , Radius 0 , Density is 100 )

No X and Y Gravity .

I am using Composer GUI

Corona SDK 2912 . and test same behavior on Smart Phone

it is a maze and if i cant fix this strange behavior players can use it to be moved to the exit ( hole ) of the maze without having to solve the maze using Vertical and Horizontal movement

@Brent i already recorded a video showing the problem . how can i send it privately to you ?

Hi @sobh,

The “( dX >= -2 and dX <= 2 )” (and similar) was really a crucial element in my example. It controls (limits) all of those diagonal swipes that you’re trying to avoid. If you want to make the swipes a bit easier to complete, but not allow swipes too far toward the 45, 135, 225, and 315 degree vectors, then change -2 and 2 to something like -5 and 5 respectively.

You also really should keep that “canBeSwiped” functionality I built in. If you take all of that out, you’re allowing the touch detection to continue even after a “successful swipe”. That is going to cause problems one way or another.

Best regards,

Brent

Hi Brent .

i test it again using your advice and it is pretty working as intended for now .

i will update this later

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