throw or fling an object with a swipe while not allowing it to be dragged

Hi

Is it possible to throw or fling an object with a swipe while preventing the object from being dragged?

I don’t want the user to be able to drag the ball to the target by continuing the swipe. The swipe is to initiate the throw and set it’s direction. Velocity will be a constant.  

The multipuck sample allows the pucks to be dragged.  

The answer in the following post does the throw/fling but the object can still be dragged.

https://forums.coronalabs.com/topic/57339-swipe-to-throw-object-without-dragging/

This is the code from that post:

[lua]

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)

[/lua]

Thanks

I’m not going to go through that code as I (currently don’t have time, but…) think the specifics of this task require some thinking about what is really needed. (I’m not saying that dragging is needed.)

I would start by defining when/where the definition of a drag would begin and the swipe (throw) would end. Use that as a base for controlling your touch event listener and I think it’ll get quite easy.

To start with, you could say that the drag is an interaction which happens when the touch event takes more than N amount of time and/or covers more than M distance. That is pretty easy to work into a simple touch event listener function.

Do you want to avoid a swipe becoming a drag? By that I mean a fast moving touch which becomes a slow moving touch? I ask this because you probably want to allow slow('ish) swipes, too.

So, the logic is fairly easy here, I think: Have a touch listener event function which checks in each ‘moved’ phase for whether the touch has been going for less than a given amount of time (you probably want to store the beginning time somewhere). Then if the touch runs for too long it’s a drag.

If, however, the touch runs beyond a given boundary but the individual moved events don’t travel very far, it’s also a drag. This would require storing each ‘moved’ phase location for use in the next event and checking the distance between them. If that distance is less than a given amount, it’s also a drag.

I know; What a drag this is.

I’m sorry.

TL;DR:

The easy approach… If the time between the began phase and any given moved or ended phase is too long, it’s a drag. If the distance travelled between any two moved phases is less than a given amount (play around with numbers here) it’s a drag. Anything else allows a swipe.

Thanks for the response. It got me thinking about what exactly I was trying to accomplish.

I realized the duration of the touch wasn’t the issue but rather the ball being acted up on once it was in motion.  And I don’t need joints so I stopped trying to work with the above code.

Below is what I now have, so far. The direction of the ball can’t be changed while in motion, but I’m having an issue with the ball going in the opposite direction of the touch’s direction.

[lua]

local ball = display.newCircle( centerX, centerY, 20 )

physics.addBody( ball, “dynamic” )

ball.gravityScale = 0

local ballActive = false

local flickStartTime = 0

local function throwBall(event)

local lx, ly = ball:getLinearVelocity() 

if (lx > 1 or ly > 1) or (lx < -1 or ly < -1) then  – check if ball still moving

print(“ball moving”)

print(lx … “,” … ly)

return

else

    if event.phase == “began” then

        flickStartTime = system.getTimer()

    elseif event.phase == “ended” then

        local flickDuration = system.getTimer() - flickStartTime 

        if flickDuration <= 0 then return end – ignore flick

        local diffX = (event.xStart - event.x) 

        local diffY = (event.yStart - event.y)

        local coef = 1 – adjust for speed

        – only react to flick if it was large enough

        if math.abs(event.xStart - event.x) > 10 or math.abs(event.yStart - event.y) > 10 then

    – ball:setLinearVelocity( diffX * coef, diffY * coef )

    ball:setLinearVelocity( diffX * coef, diffY * coef )

        end

    end

end

end

Runtime:addEventListener(“touch”, throwBall)

[/lua]

When things are opposite to expectations, negate your values.

local diffX = (event.xStart - event.x) local diffY = (event.yStart - event.y)

should be

local diffX = (event.x - event.xStart) local diffY = (event.y - event.yStart)

Thanks horacebury and Sphere Game Studios!

I’m not going to go through that code as I (currently don’t have time, but…) think the specifics of this task require some thinking about what is really needed. (I’m not saying that dragging is needed.)

I would start by defining when/where the definition of a drag would begin and the swipe (throw) would end. Use that as a base for controlling your touch event listener and I think it’ll get quite easy.

To start with, you could say that the drag is an interaction which happens when the touch event takes more than N amount of time and/or covers more than M distance. That is pretty easy to work into a simple touch event listener function.

Do you want to avoid a swipe becoming a drag? By that I mean a fast moving touch which becomes a slow moving touch? I ask this because you probably want to allow slow('ish) swipes, too.

So, the logic is fairly easy here, I think: Have a touch listener event function which checks in each ‘moved’ phase for whether the touch has been going for less than a given amount of time (you probably want to store the beginning time somewhere). Then if the touch runs for too long it’s a drag.

If, however, the touch runs beyond a given boundary but the individual moved events don’t travel very far, it’s also a drag. This would require storing each ‘moved’ phase location for use in the next event and checking the distance between them. If that distance is less than a given amount, it’s also a drag.

I know; What a drag this is.

I’m sorry.

TL;DR:

The easy approach… If the time between the began phase and any given moved or ended phase is too long, it’s a drag. If the distance travelled between any two moved phases is less than a given amount (play around with numbers here) it’s a drag. Anything else allows a swipe.

Thanks for the response. It got me thinking about what exactly I was trying to accomplish.

I realized the duration of the touch wasn’t the issue but rather the ball being acted up on once it was in motion.  And I don’t need joints so I stopped trying to work with the above code.

Below is what I now have, so far. The direction of the ball can’t be changed while in motion, but I’m having an issue with the ball going in the opposite direction of the touch’s direction.

[lua]

local ball = display.newCircle( centerX, centerY, 20 )

physics.addBody( ball, “dynamic” )

ball.gravityScale = 0

local ballActive = false

local flickStartTime = 0

local function throwBall(event)

local lx, ly = ball:getLinearVelocity() 

if (lx > 1 or ly > 1) or (lx < -1 or ly < -1) then  – check if ball still moving

print(“ball moving”)

print(lx … “,” … ly)

return

else

    if event.phase == “began” then

        flickStartTime = system.getTimer()

    elseif event.phase == “ended” then

        local flickDuration = system.getTimer() - flickStartTime 

        if flickDuration <= 0 then return end – ignore flick

        local diffX = (event.xStart - event.x) 

        local diffY = (event.yStart - event.y)

        local coef = 1 – adjust for speed

        – only react to flick if it was large enough

        if math.abs(event.xStart - event.x) > 10 or math.abs(event.yStart - event.y) > 10 then

    – ball:setLinearVelocity( diffX * coef, diffY * coef )

    ball:setLinearVelocity( diffX * coef, diffY * coef )

        end

    end

end

end

Runtime:addEventListener(“touch”, throwBall)

[/lua]

When things are opposite to expectations, negate your values.

local diffX = (event.xStart - event.x) local diffY = (event.yStart - event.y)

should be

local diffX = (event.x - event.xStart) local diffY = (event.y - event.yStart)

Thanks horacebury and Sphere Game Studios!