You know how when a product is well made, if magnets are involved there is a certain snap to them. Like with the Apple Watch charger or AirPods seat in the case. It’s almost as if there’s no pull until they’re close, and then it’s a good, strong click, but pulling away again is smooth and fluid.
I’ve been trying to model this with Corona. Having been through many iterations I’ve found that a good magnetic click can be performed with a simple touch joint being engaged at the right time. Almost no modifications are needed to the default joint values.
Where the problem begins is when the object being magnetised starts to be built up with other physical attributes. For example, other bodies connected by pivot or weld joints. In particular, I get a nice, snappy magnet effect until I add a shadow body joined by a weld; Then the combined mass generates too much inertia and the effect is lost when the bodies wobble around the touch target.
My good magnet sample is below, but my question is how to keep the effect while applying it to more complex objects?
local physics = require("physics") physics.start() physics.setGravity(0,0) physics.setDrawMode("hybrid") local function touch(e) if (e.phase == "began") then e.target.hasFocus = true display.currentStage:setFocus(e.target) e.target.touchjoint = physics.newJoint( "touch", e.target, e.x, e.y ) return true elseif (e.target.hasFocus) then e.target.touchjoint:setTarget( e.x, e.y ) if (e.phase == "moved") then else e.target.hasFocus = nil display.currentStage:setFocus(nil) e.target.touchjoint:removeSelf() e.target.touchjoint = nil end return true end return false end local function newconnector( base, x, y, r ) x, y = base:localToContent( x, y ) local dot = display.newGroup() dot.x, dot.y = x, y physics.addBody( dot, "dynamic", { isSensor=true, radius=r, filter={ categoryBits=1, maskBits=2 } } ) physics.newJoint( "weld", base, dot, dot.x, dot.y ) local joint local function moveTo( target, connector, dot ) timer.performWithDelay( 350, function() joint = physics.newJoint( "touch", target, connector.x, connector.y ) joint:setTarget( dot.x, dot.y ) end, 1 ) end function dot:collision(e) if (e.phase == "began") then if (not joint) then moveTo( base, dot, e.other ) end else if (joint) then joint:removeSelf() joint = nil end end return true end dot:addEventListener( "collision" ) return dot end local function newbar( x, y ) local rect = display.newRoundedRect( x,y , 233,100 , 25 ) physics.addBody( rect, "dynamic", { isSensor=true, density=0, friction=.1, bounce=.1 } ) rect.linearDamping = 2 rect.angularDamping = 2 rect:addEventListener( "touch", touch ) newconnector( rect, -75, 0, 25 ) newconnector( rect, 75, 0, 25 ) return rect end local function newdot( x, y, r ) local dot = display.newGroup() dot.x, dot.y = x, y physics.addBody( dot, "dynamic", { isSensor=true, radius=r, filter={ categoryBits=2, maskBits=1 } } ) return dot end newbar( 200, 200 ) newdot( 233-75, 500, 25 ) newdot( 233+75, 500, 25 )