Swipe to throw object -without dragging-

Greetings everyone,

I’m trying to throw an object along the swipe direction and I found that MultiPuck example does it really well, except the object dragging part. I don’t want to drag the object, I want to make it work with Runtime touch listener and swipe throw the object to that direction without making the object move to the tap location.

How can I do it with or without MultiPuck example?

Here is the code for MultiPuck example:

function dragBody( event, params ) local body = event.target local phase = event.phase local stage = display.getCurrentStage() if "began" == phase then stage:setFocus( body, event.id ) body.isFocus = true -- Create a temporary touch joint and store it in the object for later reference if params and params.center then -- drag the body from its center point body.tempJoint = physics.newJoint( "touch", body, body.x, body.y ) else -- drag the body from the point where it was touched body.tempJoint = physics.newJoint( "touch", body, event.x, event.y ) end -- Apply optional joint parameters if params then local maxForce, frequency, dampingRatio if params.maxForce then -- Internal default is (1000 \* mass), so set this fairly high if setting manually body.tempJoint.maxForce = params.maxForce end if params.frequency then -- This is the response speed of the elastic joint: higher numbers = less lag/bounce body.tempJoint.frequency = params.frequency end if params.dampingRatio then -- Possible values: 0 (no damping) to 1.0 (critical damping) body.tempJoint.dampingRatio = params.dampingRatio end end elseif body.isFocus then if "moved" == phase then -- Update the joint to track the touch body.tempJoint:setTarget( event.x, event.y ) elseif "ended" == phase or "cancelled" == phase then stage:setFocus( body, nil ) body.isFocus = false -- Remove the joint when the touch ends body.tempJoint:removeSelf() end end -- Stop further propagation of touch event return true end

I think I answered a similar question here (see video link in post):

https://forums.coronalabs.com/topic/57314-how-to-drag-and-throw-an-objectvideo/

It may help.

Hi Ed, it’s been a long time :slight_smile:

I’ve seen it but the player still needs to drag the object in that video. I wonder if there’s a way without dragging the object, like a swipe on the screen.

Yes it has.  :smiley:

Before I try to answer, is there just one object?  If not, how do you know which object needs to be dragged/thrown/etc.?

… or is this an object generated and then thrown after the swipe?  Please give me some more context.  I’m a little confused on the situation.

Hi @bgmadclown,

I think I know what you’re getting at. You want to be able to touch the screen anywhere, move your finger, and have the puck respond as if you were dragging it, even if your finger isn’t actually touching the puck. If that’s what you’re going for, then it’s definitely possible. Here is a simple main.lua that achieves this effect:

centerX = display.contentCenterX centerY = display.contentCenterY screenTop = math.floor(display.screenOriginY) screenLeft = math.floor(display.screenOriginX) screenBottom = display.contentHeight - screenTop screenRight = display.contentWidth - screenLeft screenWidth = screenRight - screenLeft screenHeight = screenBottom - screenTop local physics = require("physics") physics.start() local leftWall = display.newRect(screenLeft - 10, centerY, 20, screenHeight) local rightWall = display.newRect(screenRight + 10, centerY, 20, screenHeight) local topWall = display.newRect(centerX, screenTop - 10, screenWidth, 20) local bottomWall = display.newRect(centerX, screenBottom + 10, screenWidth, 20) physics.addBody(leftWall, "static") physics.addBody(rightWall, "static") physics.addBody(topWall, "static") physics.addBody(bottomWall, "static") local square = display.newRect(centerX, centerY, screenWidth\*.075, screenWidth\*.075) physics.addBody(square) square.gravityScale = 0 local tempBody local function touchListener(event) local phase=event.phase if phase == "began" then tempBody = display.newCircle(event.x, event.y, 30) tempBody.isVisible=false physics.addBody(tempBody) tempBody.isSensor = true tempBody.joint = physics.newJoint("touch", tempBody, event.x, event.y) function tempBody.enterFrame(event) local vx, vy = tempBody:getLinearVelocity() square:setLinearVelocity(vx, vy) square.angularVelocity = tempBody.angularVelocity end Runtime:addEventListener("enterFrame", tempBody) elseif phase == "moved" then tempBody.joint:setTarget(event.x, event.y) elseif phase == "cancelled" or phase == "ended" then Runtime:removeEventListener("enterFrame", tempBody) tempBody.joint:removeSelf() display.remove(tempBody) end end Runtime:addEventListener("touch", touchListener)

That creates a square, and if you touch the screen and move your finger (or mouse), the square will react as if you were dragging it. And when you release your finger, it will continue to react as if it were “flung,” using the physics library. I achieve this effect by creating an invisible “tempBody” when you touch the screen, and applying that object’s velocity data to the square. Take a look, and let me know if this is what you were looking to do. Hope it helps!

If Jason has hit the nail on the head, no need to respond to my additional questions.  Just let us know that this solved the question.

I’ll check again tomorrow to see if this is resolved.

Hi Jason,

Yes, that’s what I was looking for. Works like a charm, thank you :slight_smile:

I’ve marked it as solved (maybe I should add “fling”, “flick” to keywords for other people). Thank you, Ed & Jason, for your help :slight_smile:

One more question, regarding both the MultiPuck code and the one Jason submitted: Can we detect if the object has stopped after we throw? Is there any way to check for objects’ current velocity?

You can find a physic body’s velocity by using the object:getLinearVelocity() API. You can set up a timer to check the velocity at regular intervals and perform some function if the object has stopped, or you could use a Runtime enterFrame listener to check it constantly. I’d say that listening for an absolute zero velocity value might be a little too strict. You might want to set a threshold (vx and vy both below .01, for example) below which you will run your code, in case your object still has some minuscule velocity values that are so small as to be imperceptible to the user.

Good luck!

I’ll probably check for a change in position over time method. Thank you again, Jason :slight_smile:

I think I answered a similar question here (see video link in post):

https://forums.coronalabs.com/topic/57314-how-to-drag-and-throw-an-objectvideo/

It may help.

Hi Ed, it’s been a long time :slight_smile:

I’ve seen it but the player still needs to drag the object in that video. I wonder if there’s a way without dragging the object, like a swipe on the screen.

Yes it has.  :smiley:

Before I try to answer, is there just one object?  If not, how do you know which object needs to be dragged/thrown/etc.?

… or is this an object generated and then thrown after the swipe?  Please give me some more context.  I’m a little confused on the situation.

Hi @bgmadclown,

I think I know what you’re getting at. You want to be able to touch the screen anywhere, move your finger, and have the puck respond as if you were dragging it, even if your finger isn’t actually touching the puck. If that’s what you’re going for, then it’s definitely possible. Here is a simple main.lua that achieves this effect:

centerX = display.contentCenterX centerY = display.contentCenterY screenTop = math.floor(display.screenOriginY) screenLeft = math.floor(display.screenOriginX) screenBottom = display.contentHeight - screenTop screenRight = display.contentWidth - screenLeft screenWidth = screenRight - screenLeft screenHeight = screenBottom - screenTop local physics = require("physics") physics.start() local leftWall = display.newRect(screenLeft - 10, centerY, 20, screenHeight) local rightWall = display.newRect(screenRight + 10, centerY, 20, screenHeight) local topWall = display.newRect(centerX, screenTop - 10, screenWidth, 20) local bottomWall = display.newRect(centerX, screenBottom + 10, screenWidth, 20) physics.addBody(leftWall, "static") physics.addBody(rightWall, "static") physics.addBody(topWall, "static") physics.addBody(bottomWall, "static") local square = display.newRect(centerX, centerY, screenWidth\*.075, screenWidth\*.075) physics.addBody(square) square.gravityScale = 0 local tempBody local function touchListener(event) local phase=event.phase if phase == "began" then tempBody = display.newCircle(event.x, event.y, 30) tempBody.isVisible=false physics.addBody(tempBody) tempBody.isSensor = true tempBody.joint = physics.newJoint("touch", tempBody, event.x, event.y) function tempBody.enterFrame(event) local vx, vy = tempBody:getLinearVelocity() square:setLinearVelocity(vx, vy) square.angularVelocity = tempBody.angularVelocity end Runtime:addEventListener("enterFrame", tempBody) elseif phase == "moved" then tempBody.joint:setTarget(event.x, event.y) elseif phase == "cancelled" or phase == "ended" then Runtime:removeEventListener("enterFrame", tempBody) tempBody.joint:removeSelf() display.remove(tempBody) end end Runtime:addEventListener("touch", touchListener)

That creates a square, and if you touch the screen and move your finger (or mouse), the square will react as if you were dragging it. And when you release your finger, it will continue to react as if it were “flung,” using the physics library. I achieve this effect by creating an invisible “tempBody” when you touch the screen, and applying that object’s velocity data to the square. Take a look, and let me know if this is what you were looking to do. Hope it helps!

If Jason has hit the nail on the head, no need to respond to my additional questions.  Just let us know that this solved the question.

I’ll check again tomorrow to see if this is resolved.

Hi Jason,

Yes, that’s what I was looking for. Works like a charm, thank you :slight_smile:

I’ve marked it as solved (maybe I should add “fling”, “flick” to keywords for other people). Thank you, Ed & Jason, for your help :slight_smile:

One more question, regarding both the MultiPuck code and the one Jason submitted: Can we detect if the object has stopped after we throw? Is there any way to check for objects’ current velocity?

You can find a physic body’s velocity by using the object:getLinearVelocity() API. You can set up a timer to check the velocity at regular intervals and perform some function if the object has stopped, or you could use a Runtime enterFrame listener to check it constantly. I’d say that listening for an absolute zero velocity value might be a little too strict. You might want to set a threshold (vx and vy both below .01, for example) below which you will run your code, in case your object still has some minuscule velocity values that are so small as to be imperceptible to the user.

Good luck!

I’ll probably check for a change in position over time method. Thank you again, Jason :slight_smile: