setting limits to dragging objects

Hi, I’ve been Setting a dragging property to a group of objects called shakeableGroup, the drag works but then I wanted to set some limits to the distance that it could be dragged i’ve done different attempts and the dragging property ends up deactivating after the first drag reaches its limits, and it doesn’t let me drag it back, so far my last attempt was:

hasBeenMovedRight = false

– touch listener function

function shakeableGroup:touch( event )

if hasBeenMovedRight == false and shakeableGroup.x <= (display.contentWidth/2) then

    if event.phase == “began” then

        self.markX = self.x    – store x location of object

        self.markY = self.y    – store y location of object

    elseif event.phase == “moved” then

        local x = (event.x - event.xStart) + self.markX

        local y = (event.y - event.yStart) + self.markY

        

        self.x, self.y = x, y   

        

    end

    if event.phase == “ended” then

    hasBeenMovedRight = true 

    end

    return true

end

if hasBeenMovedRight == true and shakeableGroup.x >= 0 then

    if event.phase == “began” then

        self.markX = self.x    – store x location of object

        self.markY = self.y    – store y location of object

    elseif event.phase == “moved” then

        local x = (event.x - event.xStart) + self.markX

        local y = (event.y - event.yStart) + self.markY

        

        self.x, self.y = x, y   

    end

     if event.phase == “ended” then

    hasBeenMovedRight = false 

    end

return true  

end

end

help is much appreciated 

Not 100% what you were asking, so I supplied some code below that covers all the bases I can think of.

Here is how to modify the code:

https://www.youtube.com/watch?v=JEyS-hIoV0s

Here is the code:

local function vecAdd( x1, y1, x2, y2 ) return x1 + x2, y1 + y2 end local function vecSub( x2, y2, x1, y1 ) return x2-x1, y2-y1 end local function vecLen( x, y ) return math.sqrt( x \* x + y \* y ) end local function vecNorm( x, y ) local len = vecLen( x, y ) return x/len, y/len end local function vecScale( x, y, s ) return x \*s, y \* s end local onTouch = function( self, event ) local phase = event.phase if( phase == "began" ) then self.isFocus = true self.x0 = self.x self.y0 = self.y display.currentStage:setFocus( self, event.id ) elseif( self.isFocus ) then local x,y = event.x, event.y if( phase == "ended" or phase == "cancelled" ) then self.isFocus = false display.currentStage:setFocus( self, nil ) end local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 ) local len = vecLen( vx, vy ) print(vx,vy,len) if( len \> self.maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, self.maxDragDist ) vx,vy = vecAdd( self.x0, self.y0, vx, vy ) self.x = vx self.y = vy else self.x = event.x self.y = event.y end end return true end local tmp = display.newCircle( 100, 100, 10 ) tmp.maxDragDist = 100 -- pixels tmp.x0 = tmp.x tmp.y0 = tmp.y tmp.touch = onTouch tmp:addEventListener( "touch" )

Thanks for posting. I guess I should have explained  little more. its actually the first version you mentioned on the video the one I want. 

I tried the code and it works fine with the Circle. unfortunately when I tried it with the display group I want to move, it only works with no lines of code commented out. Im not sure if this is because display groups might have different properties. Here is what I tried based on the video:

 [lua]

local function vecAdd( x1, y1, x2, y2  )   

   return x1 + x2, y1 + y2

end

local function vecSub( x2, y2, x1, y1  )   

   return x2-x1, y2-y1

end

local function vecLen( x, y )

   return math.sqrt( x * x + y * y )

end

local function vecNorm( x, y ) 

    local len = vecLen( x, y )

    return x/len, y/len

end

local function vecScale( x, y, s )

   return x *s, y * s

end

local onTouch = function( self, event )

local phase = event.phase

if( phase == “began” ) then

self.isFocus = true

–self.x0 = self.x

–self.y0 = self.y

display.currentStage:setFocus( self, event.id )

elseif( self.isFocus ) then

local x,y = event.x, event.y

if( phase == “ended” or phase == “cancelled” ) then

self.isFocus = false

display.currentStage:setFocus( self, nil )

end

local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 )

local len = vecLen( vx, vy )

print(vx,vy,len)

if( len > self.maxDragDist ) then

vx,vy = vecNorm( vx, vy )

vx,vy = vecScale( vx, vy, self.maxDragDist )

vx,vy = vecAdd( self.x0, self.y0, vx, vy )

–self.x = vx

–self.y = vy

else

self.x = event.x

self.y = event.y

end

end

return true

end

–local tmp = display.newCircle( 100, 100, 10 )

shakeableGroup.maxDragDist = 100 – pixels

shakeableGroup.x0 = shakeableGroup.x

shakeableGroup.y0 = shakeableGroup.y

shakeableGroup.touch = onTouch

shakeableGroup:addEventListener( “touch” )

[/lua]

** FIXED TYPO - If you get weird jumps get the code again ***

Groups don’t receive touches.  

You’ll need to do something a little more complicated.  You can either use a Runtime:touch() listener, or a proxy object that drags the group.  I always do the latter.  

Here is the code for that (math functions are the same so not included below):

local onTouch = function( self, event ) local phase = event.phase local dragLayer = self.dragLayer if( not dragLayer ) then return end local maxDragDist = dragLayer.maxDragDist or 100 if( phase == "began" ) then self.isFocus = true self.x0 = event.x self.y0 = event.y dragLayer.x0 = dragLayer.x -- comment out if you want fixed x0 dragLayer.y0 = dragLayer.y -- comment out if you want fixed y0 display.currentStage:setFocus( self, event.id ) elseif( self.isFocus ) then local x,y = event.x, event.y if( phase == "ended" or phase == "cancelled" ) then self.isFocus = false display.currentStage:setFocus( self, nil ) end local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 ) local len = vecLen( vx, vy ) if( len \> maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, maxDragDist ) dragLayer.x = dragLayer.x0 + vx -- comment out if you don't want updates past maxDragDist dragLayer.y = dragLayer.y0 + vy -- comment out if you don't want updates past maxDragDist else dragLayer.x = dragLayer.x0 + vx dragLayer.y = dragLayer.y0 + vy end end return true end -- Create touch 'proxy' -- Depending on case, make it before (or after group) -- local touchProxy = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight ) touchProxy.isHitTestable = true touchProxy.alpha = 0 touchProxy.touch = onTouch touchProxy:addEventListener( "touch") -- Create group -- local shakeableGroup = display.newGroup() shakeableGroup.maxDragDist = 100 -- pixels shakeableGroup.x0 = shakeableGroup.x shakeableGroup.y0 = shakeableGroup.y -- Let the touch proxy know what group it is 'dragging' touchProxy.dragLayer = shakeableGroup -- Make some content -- local tmp = display.newCircle(shakeableGroup, 100, 100, 10 ) local tmp = display.newCircle(shakeableGroup, 100, 200, 5 ) local tmp = display.newCircle(shakeableGroup, 150, 150, 15 )

PS - Your touch proxy cannot be IN the group or this method won’t work.

-Ed

Note: I typoed one line of code above, so if you got it right after I posted, go back and get the current copy with the fixes.

Hi there, on my post you tried to fix my error,

but another error came up if you have the

time could you please take a look thanks  :slight_smile:

@keelanbrison 

Are you talking about this post HERE?  If so, please don’t cross-post and hijack someone else’s forum post like you just did.  It’s just bad forums etiquette.

I watch posts I’ve answered and will generally answer back (when I have time) if there are more questions.

It works now for moving the group. I got the updated version of your code. It still does the jumps though when I comment out the section to get a fixed x0, and y0. Not sure why this is. Thanks for staying with me by the way.

The reason the old code jumped was because of this:

if( len \> maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, maxDragDist ) -- vx,vy = vecAdd( dragLayer.x0, dragLayer.y0, vx, vy ) -- Equivalent of adding twice. dragLayer.x = dragLayer.x0 + vx -- comment out if you don't want updates past maxDragDist dragLayer.y = dragLayer.y0 + vy -- comment out if you don't want updates past maxDragDist else

Note: I’m also told that I am wrong about groups receiving touches (w/o proxies).  I’ll be looking into this.  If so, that’s good news

Not 100% what you were asking, so I supplied some code below that covers all the bases I can think of.

Here is how to modify the code:

https://www.youtube.com/watch?v=JEyS-hIoV0s

Here is the code:

local function vecAdd( x1, y1, x2, y2 ) return x1 + x2, y1 + y2 end local function vecSub( x2, y2, x1, y1 ) return x2-x1, y2-y1 end local function vecLen( x, y ) return math.sqrt( x \* x + y \* y ) end local function vecNorm( x, y ) local len = vecLen( x, y ) return x/len, y/len end local function vecScale( x, y, s ) return x \*s, y \* s end local onTouch = function( self, event ) local phase = event.phase if( phase == "began" ) then self.isFocus = true self.x0 = self.x self.y0 = self.y display.currentStage:setFocus( self, event.id ) elseif( self.isFocus ) then local x,y = event.x, event.y if( phase == "ended" or phase == "cancelled" ) then self.isFocus = false display.currentStage:setFocus( self, nil ) end local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 ) local len = vecLen( vx, vy ) print(vx,vy,len) if( len \> self.maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, self.maxDragDist ) vx,vy = vecAdd( self.x0, self.y0, vx, vy ) self.x = vx self.y = vy else self.x = event.x self.y = event.y end end return true end local tmp = display.newCircle( 100, 100, 10 ) tmp.maxDragDist = 100 -- pixels tmp.x0 = tmp.x tmp.y0 = tmp.y tmp.touch = onTouch tmp:addEventListener( "touch" )

Thanks for posting. I guess I should have explained  little more. its actually the first version you mentioned on the video the one I want. 

I tried the code and it works fine with the Circle. unfortunately when I tried it with the display group I want to move, it only works with no lines of code commented out. Im not sure if this is because display groups might have different properties. Here is what I tried based on the video:

 [lua]

local function vecAdd( x1, y1, x2, y2  )   

   return x1 + x2, y1 + y2

end

local function vecSub( x2, y2, x1, y1  )   

   return x2-x1, y2-y1

end

local function vecLen( x, y )

   return math.sqrt( x * x + y * y )

end

local function vecNorm( x, y ) 

    local len = vecLen( x, y )

    return x/len, y/len

end

local function vecScale( x, y, s )

   return x *s, y * s

end

local onTouch = function( self, event )

local phase = event.phase

if( phase == “began” ) then

self.isFocus = true

–self.x0 = self.x

–self.y0 = self.y

display.currentStage:setFocus( self, event.id )

elseif( self.isFocus ) then

local x,y = event.x, event.y

if( phase == “ended” or phase == “cancelled” ) then

self.isFocus = false

display.currentStage:setFocus( self, nil )

end

local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 )

local len = vecLen( vx, vy )

print(vx,vy,len)

if( len > self.maxDragDist ) then

vx,vy = vecNorm( vx, vy )

vx,vy = vecScale( vx, vy, self.maxDragDist )

vx,vy = vecAdd( self.x0, self.y0, vx, vy )

–self.x = vx

–self.y = vy

else

self.x = event.x

self.y = event.y

end

end

return true

end

–local tmp = display.newCircle( 100, 100, 10 )

shakeableGroup.maxDragDist = 100 – pixels

shakeableGroup.x0 = shakeableGroup.x

shakeableGroup.y0 = shakeableGroup.y

shakeableGroup.touch = onTouch

shakeableGroup:addEventListener( “touch” )

[/lua]

** FIXED TYPO - If you get weird jumps get the code again ***

Groups don’t receive touches.  

You’ll need to do something a little more complicated.  You can either use a Runtime:touch() listener, or a proxy object that drags the group.  I always do the latter.  

Here is the code for that (math functions are the same so not included below):

local onTouch = function( self, event ) local phase = event.phase local dragLayer = self.dragLayer if( not dragLayer ) then return end local maxDragDist = dragLayer.maxDragDist or 100 if( phase == "began" ) then self.isFocus = true self.x0 = event.x self.y0 = event.y dragLayer.x0 = dragLayer.x -- comment out if you want fixed x0 dragLayer.y0 = dragLayer.y -- comment out if you want fixed y0 display.currentStage:setFocus( self, event.id ) elseif( self.isFocus ) then local x,y = event.x, event.y if( phase == "ended" or phase == "cancelled" ) then self.isFocus = false display.currentStage:setFocus( self, nil ) end local vx, vy = vecSub( event.x, event.y, self.x0, self.y0 ) local len = vecLen( vx, vy ) if( len \> maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, maxDragDist ) dragLayer.x = dragLayer.x0 + vx -- comment out if you don't want updates past maxDragDist dragLayer.y = dragLayer.y0 + vy -- comment out if you don't want updates past maxDragDist else dragLayer.x = dragLayer.x0 + vx dragLayer.y = dragLayer.y0 + vy end end return true end -- Create touch 'proxy' -- Depending on case, make it before (or after group) -- local touchProxy = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight ) touchProxy.isHitTestable = true touchProxy.alpha = 0 touchProxy.touch = onTouch touchProxy:addEventListener( "touch") -- Create group -- local shakeableGroup = display.newGroup() shakeableGroup.maxDragDist = 100 -- pixels shakeableGroup.x0 = shakeableGroup.x shakeableGroup.y0 = shakeableGroup.y -- Let the touch proxy know what group it is 'dragging' touchProxy.dragLayer = shakeableGroup -- Make some content -- local tmp = display.newCircle(shakeableGroup, 100, 100, 10 ) local tmp = display.newCircle(shakeableGroup, 100, 200, 5 ) local tmp = display.newCircle(shakeableGroup, 150, 150, 15 )

PS - Your touch proxy cannot be IN the group or this method won’t work.

-Ed

Note: I typoed one line of code above, so if you got it right after I posted, go back and get the current copy with the fixes.

Hi there, on my post you tried to fix my error,

but another error came up if you have the

time could you please take a look thanks  :slight_smile:

@keelanbrison 

Are you talking about this post HERE?  If so, please don’t cross-post and hijack someone else’s forum post like you just did.  It’s just bad forums etiquette.

I watch posts I’ve answered and will generally answer back (when I have time) if there are more questions.

It works now for moving the group. I got the updated version of your code. It still does the jumps though when I comment out the section to get a fixed x0, and y0. Not sure why this is. Thanks for staying with me by the way.

The reason the old code jumped was because of this:

if( len \> maxDragDist ) then vx,vy = vecNorm( vx, vy ) vx,vy = vecScale( vx, vy, maxDragDist ) -- vx,vy = vecAdd( dragLayer.x0, dragLayer.y0, vx, vy ) -- Equivalent of adding twice. dragLayer.x = dragLayer.x0 + vx -- comment out if you don't want updates past maxDragDist dragLayer.y = dragLayer.y0 + vy -- comment out if you don't want updates past maxDragDist else

Note: I’m also told that I am wrong about groups receiving touches (w/o proxies).  I’ll be looking into this.  If so, that’s good news