Changing object group changes color of object

Hi,

I am a novice programmer and for practice I am trying to make a Tetris like game. I have pasted part of my code below. So far I have gotten to a point where blocks appear on the screen and move up (they move up instead of down). I have created some loops to stop the blocks movement if other blocks are in the way, this is also working. There is one part that seems to be giving me quite a bit of trouble…

I have a block the user moves across the screen, I call this shuffle. The shuffle is used to catch blocks and then moves them horizontally. I thought a good way of accomplishing this would be to take the block approaching the shuffle out of the blockGroup (the group that goes through the movement loop) and put it in the shuffleGroup (the movement group the user controls). Each block has a specific color so I created blockTable to save the block’s color information. The problem is, when I remove the block from blockGroup and add it back to shuffleGroup the color changes. 

I have used print() to follow what is happening with the blockTable property, and it seems to assign the correct color when the block is created, but when it gets to blockMove function it is all out of whack. I can’t even find a pattern on how it is assigning the color. Please help. 

Thank you

Chase

–Creates block movement behaviors

local blockMove = function ()

   for i = 1, blockGroup.numChildren do

      if ( blockGroup[i] ~= nil ) then

         blockXStart = blockGroup[i].x

         blockYStart = blockGroup[i].y

         occupied = 0

–This changes occupied to 1, if occupied =1 move won’t happen

         for j = 1, blockGroup.numChildren do

            if ( blockGroup[j] ~= nil and blockXStart == blockGroup[j].x and ( blockYStart -26 ) == blockGroup[j].y ) then

               occupied = 1

            end

         end

–This checks to see if block is moving into space of shuffle, if so remove from blockGroup and add to shuffleGroup

         if ( blockXStart == shuffleX - 40 and blockYStart == 642 ) then

            local shuffleBlock

            blockGroup:remove(blockGroup[i])

            shuffleBlock = display.newImage( blockTable[i], shuffleX - 40, 642)

            shuffleGroup:insert( shuffleBlock )

         elseif ( blockXStart == shuffleX + 40 and blockYStart == 642 ) then

            local shuffleBlock

            blockGroup:remove(blockGroup[i])

            shuffleBlock = display.newImage( blockTable[i], shuffleX + 40, 642)

            shuffleGroup:insert( shuffleBlock )

–If block isn’t moving into shuffle space or occupied space move down

         elseif ( blockYStart > 176 and occupied == 0 ) then

            blockGroup[i].y = blockYStart - 26

         end

      end

   end

end

–Add blocks to screen

local randomBlock = function()

   blockNumber = blockNumber + 1

   choice = math.random( 100 )

   local block

   if ( choice > 66 ) then

      block = display.newImage( “red.png”, -40 + (80 * math.random( 8 ) ), 1136 )

      blockGroup:insert( block )

      blockTable[blockNumber] = “red.png”

   elseif ( choice <= 66 and choice > 33 ) then

      block = display.newImage( “blue.png”, -40 + (80 * math.random( 8 ) ), 1136 )

      blockGroup:insert( block ) 

      blockTable[blockNumber] = “blue.png”

   else

      block = display.newImage( “green.png”, -40 + (80 * math.random( 8 ) ), 1136 )

      blockGroup:insert( block )

      blockTable[blockNumber] = “green.png”

   end

end

–Timer functions to drop blocks and add movement

timer.performWithDelay( 2400, randomBlock, 0)

timer.performWithDelay( 1200, blockMove, 0)

Well, I cleaned up your code a bit (you’ll see it below.) It’s simply a cleaned up version of your code, none of the fixes I’m about to mention.

The thing I’m curious about is that you want to move a block from one group to another. The best way to do this is simply to use :insert()! An object can only be inside one group at a time, so if you insert into another group, it is removed from the first one.

shuffleGroup:insert(blockGroup[i])

That would insert a block into the first available empty spot in shuffleGroup, which is almost always shuffleGroup.numChildren+1. Anyway, this would save you a ton of trouble in terms of remembering what colour everything is supposed to be.

--Creates block movement behaviors local function blockMove() for i = blockGroup.numChildren, 1, -1 do -- If a list could reduce, always count backwards if blockGroup[i] then -- this is a much simpler way to say ~= nil blockXStart = blockGroup[i].x blockYStart = blockGroup[i].y occupied = false -- If it's zero/one, that's a boolean. Easier to use. for j = blockGroup.numChildren, 1, -1 do if blockGroup[j] and blockXStart == blockGroup[j].x and (blockYStart - 26 == blockGroup[j].y) then occupied = true end end if (blockXStart == shuffleX - 40) and blockYStart == 642 then blockGroup:remove(blockGroup[i]) local shuffleBlock = display.newImage( shuffleGroup, blockTable[i], shuffleX - 40, 642 ) -- can always specify parentgroup as first argument elseif (blockXStart == shuffleX + 40) and blockYStart == 642 then blockGroup:remove(blockGroup[i]) local shuffleBlock = display.newImage( shuffleGroup, blockTable[i], shuffleX + 40, 642 ) elseif blockYStart \> 176 and not occupied then -- not = (false or nil) -- Note that y starts at zero, so -26 means move up blockGroup[i].y = blockYStart - 26 end end end end --Add blocks to screen local function randomBlock() blockNumber = blockNumber + 1 choice = math.random( 100 ) local blockColor = "green.png" -- Just assume it's one of the colors! if choice \> 66 then -- Only need to change if it's supposed to be red... blockColor = "red.png" elseif choice \<= 66 and choice \> 33 then -- ...or blue! blockColor = "blue.png" end local block = display.newImage(blockGroup, blockColor, -40 + (80 \* math.random(8)), 1136) blockTable[blockNumber] = blockColor end

Wow! Thank you big time!

Your suggestion worked like a charm, and is so much easier to understand than what I was trying to do. I also love the cleanup you did on my code. I just learned a butt ton!

One question for you, if you don’t mind. I realize my method was very messy; storing the color in a table, removing the item, creating a new item… but do you know what might have caused the color to change when the new item was added to the group? Not that I intend to use that method, but I felt like I was beginning to understand groups and tables and this problem totally confused me.

I appreciate your help.

Chase

I’m not entirely sure, but I suspect it was because you were looking forward through the list and removing things. 

When you look forward through a list, it goes 1,2,3,4,5,etc. but if you use :remove(3), that list becomes 1,2,3 (was 4), 4 (was 5), etc. So like a stack of tetris blocks, the order is now different. What you might have recorded as red is now green because the entire stack came down one.

Ah. That makes sense. I was under the impression the table values stayed in the same slot and the table was left with a empty value.

Thank you again.

You can achieve that by setting table[index] = nil. 

table.remove() can remove indices and reorder the table.

displayObject:remove() might do either, not entirely sure.

In any case, running sync’ed tables requires a bit of troubleshooting to keep stable.

Well, I cleaned up your code a bit (you’ll see it below.) It’s simply a cleaned up version of your code, none of the fixes I’m about to mention.

The thing I’m curious about is that you want to move a block from one group to another. The best way to do this is simply to use :insert()! An object can only be inside one group at a time, so if you insert into another group, it is removed from the first one.

shuffleGroup:insert(blockGroup[i])

That would insert a block into the first available empty spot in shuffleGroup, which is almost always shuffleGroup.numChildren+1. Anyway, this would save you a ton of trouble in terms of remembering what colour everything is supposed to be.

--Creates block movement behaviors local function blockMove() for i = blockGroup.numChildren, 1, -1 do -- If a list could reduce, always count backwards if blockGroup[i] then -- this is a much simpler way to say ~= nil blockXStart = blockGroup[i].x blockYStart = blockGroup[i].y occupied = false -- If it's zero/one, that's a boolean. Easier to use. for j = blockGroup.numChildren, 1, -1 do if blockGroup[j] and blockXStart == blockGroup[j].x and (blockYStart - 26 == blockGroup[j].y) then occupied = true end end if (blockXStart == shuffleX - 40) and blockYStart == 642 then blockGroup:remove(blockGroup[i]) local shuffleBlock = display.newImage( shuffleGroup, blockTable[i], shuffleX - 40, 642 ) -- can always specify parentgroup as first argument elseif (blockXStart == shuffleX + 40) and blockYStart == 642 then blockGroup:remove(blockGroup[i]) local shuffleBlock = display.newImage( shuffleGroup, blockTable[i], shuffleX + 40, 642 ) elseif blockYStart \> 176 and not occupied then -- not = (false or nil) -- Note that y starts at zero, so -26 means move up blockGroup[i].y = blockYStart - 26 end end end end --Add blocks to screen local function randomBlock() blockNumber = blockNumber + 1 choice = math.random( 100 ) local blockColor = "green.png" -- Just assume it's one of the colors! if choice \> 66 then -- Only need to change if it's supposed to be red... blockColor = "red.png" elseif choice \<= 66 and choice \> 33 then -- ...or blue! blockColor = "blue.png" end local block = display.newImage(blockGroup, blockColor, -40 + (80 \* math.random(8)), 1136) blockTable[blockNumber] = blockColor end

Wow! Thank you big time!

Your suggestion worked like a charm, and is so much easier to understand than what I was trying to do. I also love the cleanup you did on my code. I just learned a butt ton!

One question for you, if you don’t mind. I realize my method was very messy; storing the color in a table, removing the item, creating a new item… but do you know what might have caused the color to change when the new item was added to the group? Not that I intend to use that method, but I felt like I was beginning to understand groups and tables and this problem totally confused me.

I appreciate your help.

Chase

I’m not entirely sure, but I suspect it was because you were looking forward through the list and removing things. 

When you look forward through a list, it goes 1,2,3,4,5,etc. but if you use :remove(3), that list becomes 1,2,3 (was 4), 4 (was 5), etc. So like a stack of tetris blocks, the order is now different. What you might have recorded as red is now green because the entire stack came down one.

Ah. That makes sense. I was under the impression the table values stayed in the same slot and the table was left with a empty value.

Thank you again.

You can achieve that by setting table[index] = nil. 

table.remove() can remove indices and reorder the table.

displayObject:remove() might do either, not entirely sure.

In any case, running sync’ed tables requires a bit of troubleshooting to keep stable.