How to link two display objects, locking relative positions?

Hi, I’m trying to connect two images-  a sprite with physics applied and a background lighting effect (a rotating png image). When I move one, I’d like to the other to be fixed and move with it, as if they were one display object.

What’s the best approach?

If I apply physics to both objects they won’t stay at the same position.

I’ve tried to put them in the same display group but I can’t seem to position the group.

Eventually I’d like to spawn these grouped pairs and have them fall under gravity from a spawn object off screen… but that’s the next hurdle.

Thanks for any pointers.

[lua]

local lightingeffect= display.newImageRect( “glimmer.png”, 35, 35 )

lightingeffect.anchorX = 0.5

lightingeffect.anchorY = 0.5

lightingeffect.x, lightingeffect.y =  200,100

map.layer[1]:insert(lightingeffect)

local function spinGlimmer (event)

transition.to( lightingeffect, { rotation = lightingeffect.rotation-360, time=4000, onComplete=spinGlimmer } )

end

spinGlimmer ()

local object = display.newImageRect( “object.png”, 7, 12 )

object.anchorX = 0.5

object.anchorY = 0.5

object.x, object.y =  200,100

physics.addBody( object, “dynamic”, { density=1, friction=1, bounce=0.0  } )

map.layer[1]:insert(object)

[/lua]

Try this.

-- This code assumes neither object rotates, write back if you need to handle rotation -- -- obj2 follows obj1 in lock-step local obj1 = display.newCircle( 100, 100, 10 ) local obj2 = display.newCircle( 100, 150, 10 ) obj2.xOffset = obj2.x - obj1.x obj2.yOffset = obj2.y - obj1.y obj2.linkObj = obj1 obj2.enterFrame = function( self ) if( self.linkObj.removeSelf == nil ) then Runtime:removeEventListener( "enterFrame", self ) return end self.x = self.linkObj.x + self.xOffset self.y = self.linkObj.y + self.yOffset end Runtime:addEventListener( "enterFrame", obj2 )

Just to be clear, obj2 doesn’t rotate with obj1.  It merely maintains the original  < x , y > offset.  Maintaining the offset and rotation about obj1 is possible too, but requires more math.

Note: Some will suggest using physics joints, but I find they lack the rigidity necessary for true lock-step tracking, and why use physics when the cost of doing it the above way it cheap?

Hi roaminggamer, thanks a lot for your help.

Other than the transition function rotating the lighting effect, I’m not overly concerned about rotation, but would your code allow for natural physics motion (perhaps including rotation)?

This is a big help, many thanks.

  1. re: Natural - The object that is linked to the moving object will maintain its original position relative to the offset you specify, so if the moving object is ‘natural’, the linked object will look natural too.

  2. As I said, the above code does NOT handle rotating about the object it is linked to.  

From the above example, if obj1 move left by 100 pixels and rotates by +45 degrees, obj1 will move left 100 pixels, but not do anything to account for the rotation.  

Here is some back of the napkin code for making obj2 move with obj1 in lock-step, and rotate about obj1 if it rotates:

local function vecSub( b, a ) local x = b.x - a.x local y = b.y - a.y return x,y 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 vec2Angle( x, y ) return math.ceil( math.atan2( y, x ) \* 180 / math.pi) + 90 end local angle2Vec( angle ) local screenAngle = math.rad( -(angle+90) ) return -math.cos( screenAngle ), math.sin( screenAngle ) end local obj1 = display.newCircle( 100, 100, 10 ) local obj2 = display.newCircle( 150, 150, 10 ) -- Double check these steps (remember, back of the napkin work here) local vx,vy = vecSub( obj2, obj1 ) obj2.linkObj = obj1 obj2.deltaAngle = vec2Angle( vx, vy ) - obj1.rotation obj2.deltaAngle2 = obj2.rotation - obj1.rotation obj2.offsetDist = vecLen( vx, vy ) obj2.enterFrame = function( self ) local lx,ly,lr self.linkObj.x, self.linkObj.y, self.linkObj.rotation local angle = lr + self.deltaAngle local vx,vy = angle2Vec( angle ) vx,vy = vecNorm(vx,vy) vx,vy = vecScale( vx, vy, self.offsetDist) self.x = lx + vx self.y = ly + vy self.rotation = lr + self.deltaAngle2 end Runtime:addEventListener( "enterFrame", obj2 )

WARNING - Only tested in the brain-simulator so there may by syntax errors.  I believe the steps themselves are correct however.

Brilliant, thank you very much roaminggamer, I’m much obliged.

Note: I just updated the code as I had the angle add/subtract backwards.  Let me know if it doesn’t work as expected.

Try this.

-- This code assumes neither object rotates, write back if you need to handle rotation -- -- obj2 follows obj1 in lock-step local obj1 = display.newCircle( 100, 100, 10 ) local obj2 = display.newCircle( 100, 150, 10 ) obj2.xOffset = obj2.x - obj1.x obj2.yOffset = obj2.y - obj1.y obj2.linkObj = obj1 obj2.enterFrame = function( self ) if( self.linkObj.removeSelf == nil ) then Runtime:removeEventListener( "enterFrame", self ) return end self.x = self.linkObj.x + self.xOffset self.y = self.linkObj.y + self.yOffset end Runtime:addEventListener( "enterFrame", obj2 )

Just to be clear, obj2 doesn’t rotate with obj1.  It merely maintains the original  < x , y > offset.  Maintaining the offset and rotation about obj1 is possible too, but requires more math.

Note: Some will suggest using physics joints, but I find they lack the rigidity necessary for true lock-step tracking, and why use physics when the cost of doing it the above way it cheap?

Hi roaminggamer, thanks a lot for your help.

Other than the transition function rotating the lighting effect, I’m not overly concerned about rotation, but would your code allow for natural physics motion (perhaps including rotation)?

This is a big help, many thanks.

  1. re: Natural - The object that is linked to the moving object will maintain its original position relative to the offset you specify, so if the moving object is ‘natural’, the linked object will look natural too.

  2. As I said, the above code does NOT handle rotating about the object it is linked to.  

From the above example, if obj1 move left by 100 pixels and rotates by +45 degrees, obj1 will move left 100 pixels, but not do anything to account for the rotation.  

Here is some back of the napkin code for making obj2 move with obj1 in lock-step, and rotate about obj1 if it rotates:

local function vecSub( b, a ) local x = b.x - a.x local y = b.y - a.y return x,y 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 vec2Angle( x, y ) return math.ceil( math.atan2( y, x ) \* 180 / math.pi) + 90 end local angle2Vec( angle ) local screenAngle = math.rad( -(angle+90) ) return -math.cos( screenAngle ), math.sin( screenAngle ) end local obj1 = display.newCircle( 100, 100, 10 ) local obj2 = display.newCircle( 150, 150, 10 ) -- Double check these steps (remember, back of the napkin work here) local vx,vy = vecSub( obj2, obj1 ) obj2.linkObj = obj1 obj2.deltaAngle = vec2Angle( vx, vy ) - obj1.rotation obj2.deltaAngle2 = obj2.rotation - obj1.rotation obj2.offsetDist = vecLen( vx, vy ) obj2.enterFrame = function( self ) local lx,ly,lr self.linkObj.x, self.linkObj.y, self.linkObj.rotation local angle = lr + self.deltaAngle local vx,vy = angle2Vec( angle ) vx,vy = vecNorm(vx,vy) vx,vy = vecScale( vx, vy, self.offsetDist) self.x = lx + vx self.y = ly + vy self.rotation = lr + self.deltaAngle2 end Runtime:addEventListener( "enterFrame", obj2 )

WARNING - Only tested in the brain-simulator so there may by syntax errors.  I believe the steps themselves are correct however.

Brilliant, thank you very much roaminggamer, I’m much obliged.

Note: I just updated the code as I had the angle add/subtract backwards.  Let me know if it doesn’t work as expected.