HELP please, im done... (Problem with :toFront())

Hello!
Can’t figure out why the: toFront () function changes the value in the table?

local function AddAnimationScene(Data)
	print_r(Data)	
	CreateBlur()
	--Scene
	for i=1, #Data do
		local GetTargetRole = Data[i]["role"]
		local GetTargetIndex = Data[i]["index"]
		local GetTargetIsMove = Data[i]["ismove"]
		if GetTargetIndex == "hero" then
			for k=1, SlotGroupsHeroes.numChildren do
				if SlotGroupsHeroes[k] and tonumber(SlotGroupsHeroes[k].num) == tonumber(Data[i]["id"]) then
					local GetTarget = SlotGroupsHeroes[k]
					GetTarget.alpha =1
					GetTarget.values = {id=GetTarget.num, role=GetTargetRole, ismove=GetTargetIsMove, position={GetTarget.x, GetTarget.y},scale={GetTarget.xScale, GetTarget.yScale}}
					print(GetTarget.num, ".hero")
					GetTarget.parent:remove(GetTarget)
					AnimationGroup:insert(GetTarget)
				end
			end
		elseif GetTargetIndex == "creep" then
			for k=1, SlotGroupsEnemy.numChildren do
				if SlotGroupsEnemy[k] and tonumber(SlotGroupsEnemy[k].num) == tonumber(Data[i]["id"]) then
					local GetTarget = SlotGroupsEnemy[k]
					GetTarget.alpha =1
					GetTarget.values = {id=GetTarget.num, role=GetTargetRole, ismove=GetTargetIsMove, position={GetTarget.x, GetTarget.y},scale={GetTarget.xScale, GetTarget.yScale}}
					print(GetTarget.num, ".enemy")
					GetTarget.parent:remove(GetTarget)
					AnimationGroup:insert(GetTarget)
				end
			end
		end
	end
	for i=1, SlotGroupsEnemy.numChildren do
		if not SlotGroupsEnemy[i] then return true end
		SlotGroupsEnemy[i].alpha = 0.3
	end
	for i=1, SlotGroupsHeroes.numChildren do
		if not SlotGroupsHeroes[i] then return true end
		SlotGroupsHeroes[i].alpha = 0.3
	end
	local CounterHeroes = 0
	local CounterCreeps = 0
	for i=1, AnimationGroup.numChildren do
		local GetTarget = AnimationGroup[i]
		local GetIdenty = GetTarget.panelinfo.id
		local GetRole = GetTarget.values["role"]
		local GetIsMove = GetTarget.values["ismove"]
		local GetX = GetTarget.x
		local GetY = GetTarget.y
		local GetxS = GetTarget.xScale
		local GetyS = GetTarget.yScale
			local ScaleValueX
			local ScaleValueY
			local Scale = 0.5
			if GetxS == -1 then
				ScaleValueX = GetxS-Scale
			else
				ScaleValueX = GetxS+Scale
			end
			ScaleValueY = GetyS+Scale
			transition.scaleTo( GetTarget, { xScale=ScaleValueX, yScale=ScaleValueY, time=TimeToDoAnim, transition=easing.inQuart } )
		
		if GetIsMove == "move" then
			if GetRole == "target" then
				if GetIdenty == "hero" then
					local SetToCenter = (_W/2)-(GetTarget.width/1.8)
					transition.moveTo( GetTarget, { x=SetToCenter, time=TimeToDoAnim, transition=easing.inQuart } )
					--transition.moveTo( GetTarget, { x=SetToCenter, time=TimeToDoAnim, transition=easing.inQuart } )
				elseif GetIdenty == "creep" then
					local SetToCenter = (_W/2)+(GetTarget.width/1.8)+(tonumber(CounterCreeps)*180)
					transition.moveTo( GetTarget, { x=SetToCenter, time=TimeToDoAnim, transition=easing.inQuart } )
				end
			elseif GetRole == "director" then
				if GetIdenty == "hero" then
					local SetToCenter = (_W/2)-(GetTarget.width/1.8)-(tonumber(CounterHeroes)*380)
					transition.moveTo( GetTarget, { x=SetToCenter, time=TimeToDoAnim, transition=easing.inQuart } )
				elseif GetIdenty == "creep" then
					local SetToCenter = (_W/2)+(GetTarget.width/1.8)
					transition.moveTo( GetTarget, { x=SetToCenter, time=TimeToDoAnim, transition=easing.inQuart } )
				end
			end
		elseif GetIsMove == "nomove" then
			if GetRole == "target" then
				if GetIdenty == "hero" then
					transition.moveTo( GetTarget, { x=GetTarget.x+150, time=TimeToDoAnim, transition=easing.inQuart } )
				elseif GetIdenty == "creep" then
					transition.moveTo( GetTarget, { x=GetTarget.x-150, time=TimeToDoAnim, transition=easing.inQuart } )
				end
			elseif GetRole == "director" then
				if GetIdenty == "hero" then
					transition.moveTo( GetTarget, { x=GetTarget.x+150, time=TimeToDoAnim, transition=easing.inQuart } )
				elseif GetIdenty == "creep" then
					transition.moveTo( GetTarget, { x=GetTarget.x-150, time=TimeToDoAnim, transition=easing.inQuart } )
				end
			end
		end
		--transition.moveTo( GetTarget, { x=GetTarget.x+150, y=GetTarget.y-250, time=TimeToAnim-(TimeToAnim-450), transition=easing.continuousLoop } )
		if GetIdenty == "hero" then
			CounterHeroes = CounterHeroes +1
		elseif GetIdenty == "creep" then
			CounterCreeps = CounterCreeps +1
		end
	end
	--------
	local function DoEndAnimation()
		RemoveBlur()
		for i=1, #Data do
			for k=1, AnimationGroup.numChildren do
				if AnimationGroup[k] and tostring(Data[i]["index"]) == "hero" and tostring(AnimationGroup[k].panelinfo.id) == "hero" and tonumber(Data[i]["id"]) == tonumber(AnimationGroup[k].num) then
					local GetTarget = AnimationGroup[k]
					print(GetTarget.num, "-insertBack.SlotGroupsHeroes")
					local SetBackX = GetTarget.values["position"][1]
					local SetBackY = GetTarget.values["position"][2]
					-- GetTarget.x = GetTarget.values["position"][1]
					-- GetTarget.y = GetTarget.values["position"][2]
					transition.moveTo( GetTarget, { x=SetBackX, y=SetBackY, time=math.floor(TimeToDoAnim/2), transition=easing.inQuart } )

					local SetBackxS = GetTarget.values["scale"][1]
					local SetBackyS  = GetTarget.values["scale"][2]
					-- GetTarget.xScale = GetTarget.values["scale"][1]
					-- GetTarget.yScale = GetTarget.values["scale"][2]
					transition.scaleTo( GetTarget, { xScale=SetBackxS, yScale=SetBackyS, time=math.floor(TimeToDoAnim/2), transition=easing.inQuart } )
					GetTarget.values = nil
					GetTarget.parent:remove(GetTarget)
					SlotGroupsHeroes:insert(GetTarget)
				elseif AnimationGroup[k] and tostring(Data[i]["index"]) == "creep" and tostring(AnimationGroup[k].panelinfo.id) == "creep" and tonumber(Data[i]["id"]) == tonumber(AnimationGroup[k].num) then
					local GetTarget = AnimationGroup[k]
					print(GetTarget.num, "-insertBack.SlotGroupsEnemy")
					local SetBackX = GetTarget.values["position"][1]
					local SetBackY = GetTarget.values["position"][2]
					-- GetTarget.x = GetTarget.values["position"][1]
					-- GetTarget.y = GetTarget.values["position"][2]
					transition.moveTo( GetTarget, { x=SetBackX, y=SetBackY, time=math.floor(TimeToDoAnim/2), transition=easing.inQuart } )
					
					local SetBackxS = GetTarget.values["scale"][1]
					local SetBackyS  = GetTarget.values["scale"][2]
					-- GetTarget.xScale = GetTarget.values["scale"][1]
					-- GetTarget.yScale = GetTarget.values["scale"][2]
					transition.scaleTo( GetTarget, { xScale=SetBackxS, yScale=SetBackyS, time=math.floor(TimeToDoAnim/2), transition=easing.inQuart } )
					
					GetTarget.values = nil
					GetTarget.parent:remove(GetTarget)
					SlotGroupsEnemy:insert(GetTarget)
				end
			end
		end
		for i=1, SlotGroupsEnemy.numChildren do
			for k=1, SlotGroupsEnemy.numChildren do
				if SlotGroupsEnemy[i].num == k then
					SlotGroupsEnemy[i]:toFront()
					SlotGroupsEnemy[i].alpha = 1
				end
			end
		end
		for i=1, SlotGroupsHeroes.numChildren do
			SlotGroupsHeroes[i].alpha = 1
		end
	end
	timer.performWithDelay(tonumber(TimeToAnim-TimeToDoAnim), function()
		DoEndAnimation()
	end)
	for i=1, AnimationGroup.numChildren do
		--if not AnimationGroup[i] then return true end
		for k=1, AnimationGroup.numChildren do
			if tonumber(AnimationGroup[i].num) == k and tostring(AnimationGroup[i].panelinfo.id) == "hero" then
				print("----------")
				print(AnimationGroup[i].num, "good ID")
				AnimationGroup[i]:toFront()
				print(AnimationGroup[i].num, "bad ID")
				print("----------")
			end
		end
	end
end

Prints:

00:08:33.932 UIStart: blue
00:08:39.313 [1] => table: 176190F8 {
00:08:39.313 [id] => 3
00:08:39.313 [role] => target
00:08:39.313 [index] => hero
00:08:39.313 [ismove] => nomove
00:08:39.313 }
00:08:39.313 [2] => table: 176190F8 {
00:08:39.313 [id] => 4
00:08:39.313 [role] => target
00:08:39.313 [index] => hero
00:08:39.313 [ismove] => nomove
00:08:39.313 }
00:08:39.313 [3] => table: 176190F8 {
00:08:39.313 [id] => 1
00:08:39.313 [role] => target
00:08:39.313 [index] => hero
00:08:39.313 [ismove] => nomove
00:08:39.313 }
00:08:39.313 [4] => table: 176190F8 {
00:08:39.313 [id] => 2
00:08:39.313 [role] => target
00:08:39.313 [index] => hero
00:08:39.313 [ismove] => nomove
00:08:39.313 }
00:08:39.313 [5] => table: 176190F8 {
00:08:39.313 [id] => 2
00:08:39.313 [role] => director
00:08:39.313 [index] => hero
00:08:39.313 [ismove] => nomove
00:08:39.313 }
00:08:39.313 3 .hero
00:08:39.313 4 .hero
00:08:39.313 1 .hero
00:08:39.313 2 .hero
00:08:39.313 ----------
00:08:39.313 3 good ID
00:08:39.313 4 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 4 good ID
00:08:39.313 1 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 2 good ID
00:08:39.313 3 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 3 good ID
00:08:39.313 4 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 4 good ID
00:08:39.313 2 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 3 good ID
00:08:39.313 4 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 4 good ID
00:08:39.313 3 bad ID
00:08:39.313 ----------
00:08:39.313 ----------
00:08:39.313 4 good ID
00:08:39.313 4 bad ID
00:08:39.313 ----------
00:08:43.128 3 -insertBack.SlotGroupsHeroes
00:08:43.128 4 -insertBack.SlotGroupsHeroes
00:08:43.128 1 -insertBack.SlotGroupsHeroes
00:08:43.128 2 -insertBack.SlotGroupsHeroes

Because of ruin of .num, my game does chaos in order of characters

Example(Chaos):


How It should be:

Corona uses the indexes of a group to know the drawing order, where group[1] corresponds to the bottom and group[group.numChildren] is the top

When you execute group[i]:toFront() it moves your display object to the last position in the table

Using this at the end of your code should print the same ID

for i=1, AnimationGroup.numChildren do
	--if not AnimationGroup[i] then return true end
	for k=1, AnimationGroup.numChildren do
		if tonumber(AnimationGroup[i].num) == k and tostring(AnimationGroup[i].panelinfo.id) == "hero" then
			print("----------")
			print(AnimationGroup[i].num, "good ID")
			AnimationGroup[i]:toFront()
			print(AnimationGroup[AnimationGroup.numChildren].num, "same ID")
			print("----------")
		end
	end
end

I’m not sure what are you trying to do, but usually we iterate over a group backwards

for I=AnimationGroup.numChildren, 1, -1 do
	--if not AnimationGroup[i] then return true end
	for k=AnimationGroup.numChildren, 1, -1 do
		if tonumber(AnimationGroup[i].num) == k and tostring(AnimationGroup[i].panelinfo.id) == "hero" then
			print("----------")
			print(AnimationGroup[i].num, "good ID")
			AnimationGroup[i]:toFront()
			print(AnimationGroup[AnimationGroup.numChildren].num, "same ID")
			print("----------")
		end
	end
end

This should solve your issue and it use to be safer. Anyway I think there must be a better way to do what you’re trying.

2 Likes

Display groups are not really tables. This may be confusing because you can index them with numbers, but they are not the same.

You see display group ordering decides what objects are below and above each other in the rendering stack…

Let me see if I can clear this up with a small code example…

local group = display.newGroup()

local circles = {}

local redCircle = display.newCircle( group, 100, 100, 100 )
redCircle.id = "red"
redCircle:setFillColor( 1, 0, 0 )
circles[#circles+1] = redCircle

local greenCircle = display.newCircle( group, 100, 100, 100 )
greenCircle.id = "green"
greenCircle:setFillColor( 0, 1, 0 )
circles[#circles+1] = greenCircle

local blueCircle = display.newCircle( group, 100, 100, 100 )
blueCircle.id = "blue"
blueCircle:setFillColor( 0, 0, 1 )
circles[#circles+1] = blueCircle

At this point, we have:

  • a display group named group,
  • a table named circles, and
  • three circles in the group, one on top of the other.

The only visible circle is the blue one.

Now, if we do this:

for i =1, group.numChildren do
   print( group[i].id )
end

for i =1, #circles do
   print( circles[i].id )
end

We get this output in the terminal:

red
green
blue
red
green
blue

Then, if we do this:

redCircle:toFront()

for i =1, group.numChildren do
   print( group[i].id )
end

for i =1, #circles do
   print( circles[i].id )
end

We get this output in the terminal:

green
blue
red
red
green
blue

You see, the group order has changed, but the table has not.

In your code, you are making two mistakes:

  1. You are treating a display group like a table and expecting a behavior rule that does not exist. i.e. That table entries will not reorder. But, calling toFront() immediately reorders a display group.

  2. You are calling a function that reorders the group while you are iterating on the group numerically. Thus, your indexes advance, but you may end up touching the same object twice.

How do you fix this?
One way may be to simply defer that toFront() call.

Try changing this:

if tonumber(AnimationGroup[i].num) == k and tostring(AnimationGroup[i].panelinfo.id) == "hero" then
   print("----------")
   print(AnimationGroup[i].num, "good ID")
   AnimationGroup[i]:toFront()
   print(AnimationGroup[i].num, "bad ID")
   print("----------")
end

to this:

if tonumber(AnimationGroup[i].num) == k and tostring(AnimationGroup[i].panelinfo.id) == "hero" then
   print("----------")
   print(AnimationGroup[i].num, "good ID")
   local obj = AnimationGroup[i]:toFront()
   timer.performWithDelay( 1, function()  obj:toFront() end )
   print(AnimationGroup[i].num, "bad ID")
   print("----------")
end

Note: Thanks for the formatted code post.
Tip: It makes these posts more legible (better horizontal fit) if you replace all tabs with 3 or 4 spaces before pasting the code here. 3 or 4 depends on the width of your tab setting in the editor you are using.

1 Like

Fixed a few typos above. Oops!

1 Like

@roaminggamer @depilz, Thank you very much! :relieved: You help me a lot! I solved the problem and now everything works as planned!

1 Like