Moving a display object from display group to another

I could really use the help of a Corona Guru.

I’m creating a game with a layout similar to Words With Friends. The goal is to have a gameboard that you can zoom in on and pan around, and tiles along the bottom of the screen that you can drag to the game board and will snap into place.

I have created a group for the gameboard which will ultimately hold all the tiles and background image for the board etc. I have the tiles in a separate group initially because the gameboard needs to be able to zoom and move around independently of the rest of the objects on screen.

I have a touch event listener for the tiles where I also pass in the group for the gameboard. The problem is that no matter what I do, the tiles get positioned relative to the center of the boardgroup. I would like to make them position relative to the top left to avoid having to do crazy math. I tried setting the display reference point to top left but it doesn’t seem to make a difference.

When I create the gameboard group I set the reference point to center to make it easy to position. I tried setting it to top left but this didn’t seem to make a difference. The tiles always get positioned to the center of the group.

I also made the gameboard group a physics object as I found doing so makes it really easy to drag and flick it around.

My code for the event listener is below:

function tileTouch(event, boardGroup)   local body = event.target     if event.phase == "began" then     display.getCurrentStage():setFocus( body )     body.isFocus = true              body.markX = body.x -- store x location of object     body.markY = body.y -- store y location of object        elseif body.isFocus then     if event.phase == "moved" then       local x = (event.x - event.xStart) + body.markX       local y = (event.y - event.yStart) + body.markY       body.x, body.y = x, y -- move object based on calculations above            elseif event.phase == "ended" or event.phase == "cancelled" then       body:scale(1/boardGroup.scaleMax, 1/boardGroup.scaleMax)       zoomBoard(boardGroup, event)              boardGroup:setReferencePoint(display.TopLeftReferencePoint)              body.x = 0  --With everything Ive tried this always refers to the center       body.y = 0  --of the board group.                 boardGroup:insert(body)       display.getCurrentStage():setFocus( nil )       body.isFocus = false                   boardGroup:setReferencePoint( display.CenterReferencePoint )     end   end   return true end  

Please let me know if you need to see more code. Thanks!!

What version of Corona SDK are you using?

Just a couple of things about groups.  Groups don’t have a top, left or a right or a bottom.  They are technically boundless.  They have an origin, which by default is at 0, 0. When you move your group, all children move relative to it.   Also to move things between two different groups, you just insert the object into the new group.  Since groups are boundless, reference points have no effect on them.  You can set where a display object’s drawing point is using referencePoints (builds before 2000), but with builds 2000 and later you have to use AnchorPoints.   With your tile, if you set the reference point to display.TopLeftReferencePoint, then you’re controlling where the top, left corner of the tile will be drawn, but it’s still relative to the group’s origin.   With the Graphics 2.0 engine, to draw an object using the tile’s top left, you would set:  tile.anchorX = 0, tile.anchorY = 0.  The default is to draw based on the center of the tile, the anchor’s are 0.5 and 0.5.

Also, I don’t know that you can pass in parameters like that to event handlers.  

You should be able to keep the position of the tile the same in both groups, even if the group origin is in different positions, by using group:contentToLocal() and group:localToContent().

For example
 

local oldX, oldY = object.parent:localToContent(object.x, object.y); newGroup:insert(object); object.x, object.y = newGroup:contentToLocal(oldX, oldY);

You can also offset the tiles by yourself, knowing what the top-left corner should be. If it must be the total width/height of the group (this changes based on the positions of objects in it) you can do
 

newGroup:insert(object); object.x, object.y = object.x-(newGroup.width\*.5), object.y-(newGroup.height\*.5);

@Rob Miracle

Thanks for the info Rob. To be honest I’m not entirely sure what SDK version I’m using but when I go to About in the simulator I see this: Version 2013.1076 (2013.4.3). I guess I was confused because when you create a group using local group = self.view it lets you place objects with 0,0 being in the upper left corner of the screen. I’m guessing it’s different when you create a group using display.newGroup()? Does that mean that everytime you declare a new group that way the origin will always be at the center of the screen?

@hachisoft

Thanks! Using contentToLocal actually helped a lot. I think I still need to do some fancy math to get the tiles to snap to the desired coordinates but at least the tiles are being placed on the board where I let go of my finger.

You are using 1076.  This is four public builds old.  If you want to stay with Graphics 1.0,  you should upgrade to 1212, but there have been changes by Apple, Google and Facebook that make make 1212 too old to really use.  The current public build is 2100 which is graphics 2.0  based.

local group = self.view  doesn’t really create a group, it just assigns it the scene’s existing display.newGroup which is it’s self.view in that case.  Creating your own display.newGroup() would also have it’s 0,0 at the top left of the screen, so they are no different.  All groups will by default have their origin at 0, 0.  In Graphics 2.0 objects (not groups) are all drawn from the object’s center.

Rob

Thanks, Rob. I had no idea I was that far behind in the builds! I installed 2100 and it’s working great so far.

What version of Corona SDK are you using?

Just a couple of things about groups.  Groups don’t have a top, left or a right or a bottom.  They are technically boundless.  They have an origin, which by default is at 0, 0. When you move your group, all children move relative to it.   Also to move things between two different groups, you just insert the object into the new group.  Since groups are boundless, reference points have no effect on them.  You can set where a display object’s drawing point is using referencePoints (builds before 2000), but with builds 2000 and later you have to use AnchorPoints.   With your tile, if you set the reference point to display.TopLeftReferencePoint, then you’re controlling where the top, left corner of the tile will be drawn, but it’s still relative to the group’s origin.   With the Graphics 2.0 engine, to draw an object using the tile’s top left, you would set:  tile.anchorX = 0, tile.anchorY = 0.  The default is to draw based on the center of the tile, the anchor’s are 0.5 and 0.5.

Also, I don’t know that you can pass in parameters like that to event handlers.  

You should be able to keep the position of the tile the same in both groups, even if the group origin is in different positions, by using group:contentToLocal() and group:localToContent().

For example
 

local oldX, oldY = object.parent:localToContent(object.x, object.y); newGroup:insert(object); object.x, object.y = newGroup:contentToLocal(oldX, oldY);

You can also offset the tiles by yourself, knowing what the top-left corner should be. If it must be the total width/height of the group (this changes based on the positions of objects in it) you can do
 

newGroup:insert(object); object.x, object.y = object.x-(newGroup.width\*.5), object.y-(newGroup.height\*.5);

@Rob Miracle

Thanks for the info Rob. To be honest I’m not entirely sure what SDK version I’m using but when I go to About in the simulator I see this: Version 2013.1076 (2013.4.3). I guess I was confused because when you create a group using local group = self.view it lets you place objects with 0,0 being in the upper left corner of the screen. I’m guessing it’s different when you create a group using display.newGroup()? Does that mean that everytime you declare a new group that way the origin will always be at the center of the screen?

@hachisoft

Thanks! Using contentToLocal actually helped a lot. I think I still need to do some fancy math to get the tiles to snap to the desired coordinates but at least the tiles are being placed on the board where I let go of my finger.

You are using 1076.  This is four public builds old.  If you want to stay with Graphics 1.0,  you should upgrade to 1212, but there have been changes by Apple, Google and Facebook that make make 1212 too old to really use.  The current public build is 2100 which is graphics 2.0  based.

local group = self.view  doesn’t really create a group, it just assigns it the scene’s existing display.newGroup which is it’s self.view in that case.  Creating your own display.newGroup() would also have it’s 0,0 at the top left of the screen, so they are no different.  All groups will by default have their origin at 0, 0.  In Graphics 2.0 objects (not groups) are all drawn from the object’s center.

Rob

Thanks, Rob. I had no idea I was that far behind in the builds! I installed 2100 and it’s working great so far.