Move a Group which contains widget buttons

Hello,

So I was follow Newnams tutorial on Level Selection, tweaked it around, and now I have 9 widget buttons stored in a group, each of which are spaced out evenly. Now the plan is to have a button that’ll move this group of 9 levels, and bring in another 9 levels.
Code to display icons for levels:

[code] – Pots
for i = 0,2 do
for j = 1,3 do
current = i* 3+ j
levelsGroupOne[current] = widget.newButton {
label = current,
id=current,
width = 120,
height=122,
defaultColor = {255,0,0,255},
strokeColor = {0,0,0,0},
onRelease = buttonRelease
–default = square = display.newRect(0,0,120,122),
}

levelsGroupOne[current].x = 15 + (j*150)
levelsGroupOne[current].y = 275 + (i*165)

end
end[/code]

Problem is, when I try to move the objects, every time I move them back, the spacing between them messes up thus when they come back, all buttons are stacked on top of each other.

My attempt at moving (for left button only):

function goLeft(e)  
 if (e.phase == "ended") then  
 print ("scroll left");  
 --tweenLeft = transition.to (levelsGroupOne, { time = 100, delay = 1000, x = -100})  
  
 for i = 1, #levelsGroupOne do   
 transition.to (levelsGroupOne, { time = 300, delay = 0, x = -100})  
 end  
  
 end  
end  

While I’m at it, can someone please tell me how I can substitute the red-squares (used to make a button) for a graphic?

Thank you [import]uid: 184921 topic_id: 34400 reply_id: 334400[/import]

Just like to add that I have yet to make the next 9 buttons, right now I want to see if I can move one group; the next 9 buttons will be offscreen [import]uid: 184921 topic_id: 34400 reply_id: 136695[/import]

a. I don’t see any code where the widget buttons are inserted into the display group. AFAIK group[x] = object is not the same as group:insert(object) when it comes to display objects and display groups.

b. The “for” loop doesn’t support any sort of “wait” cycle, so why not just move the entire group and not the buttons individually? You could use a single transition to move the display group rather than build the 9+ transitions…

Keep in mind that you are using local addressing so objects within a displayGroup have a position relative to the reference point of the group itself. Moving objects individually can change that reference point (ie: move one button left and now the display group is technically speaking “wider”, with probably a different true zero X/Y) [import]uid: 41884 topic_id: 34400 reply_id: 136698[/import]

To answer the first point, I’ve missed that bit. Here’s the entire function along with the group:insert() bit

[lua]function scene: createScene( event )

–[[
for i = 1,100 do
print ("")
end
–]]

local group = self.view

print ("width: " … _W … " " … "height: " … _H)

local bg = display.newImageRect(“images/bgLevelSelect.png”, 640, 960) – load background
bg:setReferencePoint(display.CenterReferencePoint);
bg.x = _W/2; bg.y=_H/2;
group:insert(bg);

– Left Button –
btnLeft = display.newImageRect(“images/buttons/btnLeft.png”,296, 264);
btnLeft:setReferencePoint(display.CenterReferencePoint);
btnLeft.xScale = scale; btnLeft.yScale = scale;
btnLeft.x= 143; btnLeft.y = 775
btnLeft:addEventListener(“touch”, goLeft);

– Buy Now Button –
btnBuyGame = display.newImageRect(“images/buttons/btnBuyFullGame.png”,488,306);
btnBuyGame:setReferencePoint(display.CenterReferencePoint);
btnBuyGame.xScale = scale; btnBuyGame.yScale = scale;
btnBuyGame.x =_W/2; btnBuyGame.y = btnLeft.y;
btnBuyGame:addEventListener(“touch”, buyGame);

– Right Button –
btnRight = display.newImageRect(“images/buttons/btnRight.png”,296,264);
btnRight:setReferencePoint(display.CenterReferencePoint);
btnRight.xScale = scale; btnRight.yScale = scale;
btnRight.x = (btnLeft.x+353); btnRight.y = btnLeft.y
btnRight:addEventListener(“touch”, goRight);

– Load sheet :3
–[[local sheetOptions {

}
–]]

– Pots
for i = 0,2 do
for j = 1,3 do
current = i* 3+ j
levelsGroupOne[current] = widget.newButton {
label = current,
id=current,
width = 120,
height=122,
defaultColor = {255,0,0,255},
strokeColor = {0,0,0,0},
onRelease = buttonRelease
–default = square = display.newRect(0,0,120,122),
}

levelsGroupOne[current].x = 15 + (j*150)
levelsGroupOne[current].y = 275 + (i*165)

end
end

group:insert(btnLeft);
group:insert(btnBuyGame);
group:insert(btnRight);
group:insert( levelsGroupOne[current] )

end[/lua]

Yes, the displayGroup is local, would you suggest that I make a global one instead?

edit: Actually thinking about it, having a global displayGroup would move everything. Scratch that >.< [import]uid: 184921 topic_id: 34400 reply_id: 136701[/import]

I mean, I don’t see you inserting the level buttons into a display group. What you should be doing is this:

[code]local levelGroupsOne = display.newGroup() – somewhere

for i = 0,2 do
for j = 1,3 do
current = i* 3+ j
local button = widget.newButton { – just call it button for now
label = current,
id=current,
width = 120,
height=122,
defaultColor = {255,0,0,255},
strokeColor = {0,0,0,0},
onRelease = buttonRelease
–default = square = display.newRect(0,0,120,122),
}

button.x = 15 + (j*150) – Each button is local to this step in the loop
button.y = 275 + (i*165)
levelGroupsOne:insert(button) – but after it’s added it becomes group[#]

end
end[/code] [import]uid: 41884 topic_id: 34400 reply_id: 136703[/import]

Alright… But isn’t that what I’ve done with the group:insert(levelsGroupOne[current]) on line 72? [import]uid: 184921 topic_id: 34400 reply_id: 136707[/import]

Well, there are two problems with that approach.

  1. You are inserting all of the buttons into the same display group as first three. This makes it difficult to move your level buttons because the other buttons would go with them. Easier to just put a display group inside a display group, so that you have:

a. (main group) - left button, right button, buy button, levelGroup1, levelGroup 2, etc
b. (level group 1) - all of the level group 1 buttons
etc

Then you can just move level group 1’s x/y in a single transition and not touch any of the x/y stuff for each button. That should ensure they all stay in position.

  1. Like I said before, just calling something groupname[#] is not the same as :insert(). The only way your approach works is if levelGroupsOne is a regular table {}. Which is fine, if you need to use a regular table. But it’s easier to manage as a display group since all of the table objects are display objects.

[code]local myTable = {} – This is a regular table
– Objects in a regular table are not grouped. They move individually only.
myTable[1] = display.newRect(32,32,42,42)
myTable[2] = display.newImage(“hi.png”)

– You can still add them to a display group too, but it gets a bit complicated
local myGroup = display.newGroup()
myGroup:insert(myTable[1]) – now is both “myGroup[1]” and “myTable[1]”
myGroup:insert(myTable[2]) – now is both “myGroup[2]” and “myTable[2]”[/code]

-- Display Group only approach local myGroup = display.newGroup() for i = 1, 30 do local newButton = display.newRect(0,0,32,32) myGroup:insert(newButton) -- you can't reference newButton outside of here but its also myGroup[i] end

Display objects and groups still support named table parameters so they are pretty easy to use:

local myGroup = display.newGroup() myGroup[1] = display.newRect(0,0,32,32) -- [!] bad! causes errors. Use :insert() myGroup.leftarm = display.newRect(0,0,32,32) -- fine. it's not in the display group though. myGroup.thinking = true -- so is this myGroup.isActive = "yep" -- and this

Frequently that’s a good approach for when you need an object or functions variables to be readable outside of a function.

[code]local function makeButton(style)
local button = display.newRect(0,0,32,32)
button.style = style
return button
end

myButton = makeButton(“scarf”)
print(myButton.style) – “scarf”[/code] [import]uid: 41884 topic_id: 34400 reply_id: 136780[/import]

Just like to add that I have yet to make the next 9 buttons, right now I want to see if I can move one group; the next 9 buttons will be offscreen [import]uid: 184921 topic_id: 34400 reply_id: 136695[/import]

a. I don’t see any code where the widget buttons are inserted into the display group. AFAIK group[x] = object is not the same as group:insert(object) when it comes to display objects and display groups.

b. The “for” loop doesn’t support any sort of “wait” cycle, so why not just move the entire group and not the buttons individually? You could use a single transition to move the display group rather than build the 9+ transitions…

Keep in mind that you are using local addressing so objects within a displayGroup have a position relative to the reference point of the group itself. Moving objects individually can change that reference point (ie: move one button left and now the display group is technically speaking “wider”, with probably a different true zero X/Y) [import]uid: 41884 topic_id: 34400 reply_id: 136698[/import]

To answer the first point, I’ve missed that bit. Here’s the entire function along with the group:insert() bit

[lua]function scene: createScene( event )

–[[
for i = 1,100 do
print ("")
end
–]]

local group = self.view

print ("width: " … _W … " " … "height: " … _H)

local bg = display.newImageRect(“images/bgLevelSelect.png”, 640, 960) – load background
bg:setReferencePoint(display.CenterReferencePoint);
bg.x = _W/2; bg.y=_H/2;
group:insert(bg);

– Left Button –
btnLeft = display.newImageRect(“images/buttons/btnLeft.png”,296, 264);
btnLeft:setReferencePoint(display.CenterReferencePoint);
btnLeft.xScale = scale; btnLeft.yScale = scale;
btnLeft.x= 143; btnLeft.y = 775
btnLeft:addEventListener(“touch”, goLeft);

– Buy Now Button –
btnBuyGame = display.newImageRect(“images/buttons/btnBuyFullGame.png”,488,306);
btnBuyGame:setReferencePoint(display.CenterReferencePoint);
btnBuyGame.xScale = scale; btnBuyGame.yScale = scale;
btnBuyGame.x =_W/2; btnBuyGame.y = btnLeft.y;
btnBuyGame:addEventListener(“touch”, buyGame);

– Right Button –
btnRight = display.newImageRect(“images/buttons/btnRight.png”,296,264);
btnRight:setReferencePoint(display.CenterReferencePoint);
btnRight.xScale = scale; btnRight.yScale = scale;
btnRight.x = (btnLeft.x+353); btnRight.y = btnLeft.y
btnRight:addEventListener(“touch”, goRight);

– Load sheet :3
–[[local sheetOptions {

}
–]]

– Pots
for i = 0,2 do
for j = 1,3 do
current = i* 3+ j
levelsGroupOne[current] = widget.newButton {
label = current,
id=current,
width = 120,
height=122,
defaultColor = {255,0,0,255},
strokeColor = {0,0,0,0},
onRelease = buttonRelease
–default = square = display.newRect(0,0,120,122),
}

levelsGroupOne[current].x = 15 + (j*150)
levelsGroupOne[current].y = 275 + (i*165)

end
end

group:insert(btnLeft);
group:insert(btnBuyGame);
group:insert(btnRight);
group:insert( levelsGroupOne[current] )

end[/lua]

Yes, the displayGroup is local, would you suggest that I make a global one instead?

edit: Actually thinking about it, having a global displayGroup would move everything. Scratch that >.< [import]uid: 184921 topic_id: 34400 reply_id: 136701[/import]

I mean, I don’t see you inserting the level buttons into a display group. What you should be doing is this:

[code]local levelGroupsOne = display.newGroup() – somewhere

for i = 0,2 do
for j = 1,3 do
current = i* 3+ j
local button = widget.newButton { – just call it button for now
label = current,
id=current,
width = 120,
height=122,
defaultColor = {255,0,0,255},
strokeColor = {0,0,0,0},
onRelease = buttonRelease
–default = square = display.newRect(0,0,120,122),
}

button.x = 15 + (j*150) – Each button is local to this step in the loop
button.y = 275 + (i*165)
levelGroupsOne:insert(button) – but after it’s added it becomes group[#]

end
end[/code] [import]uid: 41884 topic_id: 34400 reply_id: 136703[/import]

Alright… But isn’t that what I’ve done with the group:insert(levelsGroupOne[current]) on line 72? [import]uid: 184921 topic_id: 34400 reply_id: 136707[/import]

Well, there are two problems with that approach.

  1. You are inserting all of the buttons into the same display group as first three. This makes it difficult to move your level buttons because the other buttons would go with them. Easier to just put a display group inside a display group, so that you have:

a. (main group) - left button, right button, buy button, levelGroup1, levelGroup 2, etc
b. (level group 1) - all of the level group 1 buttons
etc

Then you can just move level group 1’s x/y in a single transition and not touch any of the x/y stuff for each button. That should ensure they all stay in position.

  1. Like I said before, just calling something groupname[#] is not the same as :insert(). The only way your approach works is if levelGroupsOne is a regular table {}. Which is fine, if you need to use a regular table. But it’s easier to manage as a display group since all of the table objects are display objects.

[code]local myTable = {} – This is a regular table
– Objects in a regular table are not grouped. They move individually only.
myTable[1] = display.newRect(32,32,42,42)
myTable[2] = display.newImage(“hi.png”)

– You can still add them to a display group too, but it gets a bit complicated
local myGroup = display.newGroup()
myGroup:insert(myTable[1]) – now is both “myGroup[1]” and “myTable[1]”
myGroup:insert(myTable[2]) – now is both “myGroup[2]” and “myTable[2]”[/code]

-- Display Group only approach local myGroup = display.newGroup() for i = 1, 30 do local newButton = display.newRect(0,0,32,32) myGroup:insert(newButton) -- you can't reference newButton outside of here but its also myGroup[i] end

Display objects and groups still support named table parameters so they are pretty easy to use:

local myGroup = display.newGroup() myGroup[1] = display.newRect(0,0,32,32) -- [!] bad! causes errors. Use :insert() myGroup.leftarm = display.newRect(0,0,32,32) -- fine. it's not in the display group though. myGroup.thinking = true -- so is this myGroup.isActive = "yep" -- and this

Frequently that’s a good approach for when you need an object or functions variables to be readable outside of a function.

[code]local function makeButton(style)
local button = display.newRect(0,0,32,32)
button.style = style
return button
end

myButton = makeButton(“scarf”)
print(myButton.style) – “scarf”[/code] [import]uid: 41884 topic_id: 34400 reply_id: 136780[/import]