for loop not working as expected

Hey guys, I’ve never had this issue before, but for some reason either my for loop or something else is just malfunctioning in my code. Can anybody try this code?

  1. Basically a bunch of tiles are created, on top of the other.

  2. Tiles are moved down by their y property through table iteration.

  3. When they reach the near bottom of the screen they are removed and nilled

  4. Tiles that have not reached the bottom should keep going down.

Problem is it working fine, but once I reach the fourth row they all stop. It seems like an error in the way it’s looping through the table. I tried many variations of the for loop to no avail. Any help would be appreciated. 

Here’s the code:

tileTable = {} local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function createTileMap(horizontalRowLength, verticalRowLength, tileSize) for i = 1, horizontalRowLength do color1 = math.random(0, 1) tile\_Vertical = display.newRect(0, 0, tileSize, tileSize) tile\_Vertical.x = (i - .5) \* tileSize tile\_Vertical.y = screenH - (tileSize\*.5) tile\_Vertical:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Vertical) for b = 1, verticalRowLength do color1 = math.random(0, 1) tile\_Horizontal = display.newRect(0, 0, tileSize, tileSize) tile\_Horizontal.x = tile\_Vertical.x tile\_Horizontal.y = tile\_Vertical.y - (tileSize \* b) tile\_Horizontal:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Horizontal) end end end horizontalRowLength = 7 tileSize = 30 verticalRowLength = 6 createTileMap(horizontalRowLength, verticalRowLength, tileSize) function moveTiles() for i = #tileTable, 1, -1 do tile = tileTable[i] if tile ~= nil then tile.y = tile.y + 5 if tile.y \> screenH then tileTable[i]:removeSelf() tileTable[i] = nil end end end end Runtime:addEventListener("enterFrame", moveTiles)

Try this:

tileTable = {} local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function createTileMap(horizontalRowLength, verticalRowLength, tileSize) for i = 1, horizontalRowLength do color1 = math.random(0, 1) tile\_Vertical = display.newRect(0, 0, tileSize, tileSize) tile\_Vertical.x = (i - .5) \* tileSize tile\_Vertical.y = screenH - (tileSize\*.5) tile\_Vertical:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Vertical) for b = 1, verticalRowLength do color1 = math.random(0, 1) tile\_Horizontal = display.newRect(0, 0, tileSize, tileSize) tile\_Horizontal.x = tile\_Vertical.x tile\_Horizontal.y = tile\_Vertical.y - (tileSize \* b) tile\_Horizontal:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Horizontal) end end end horizontalRowLength = 7 tileSize = 30 verticalRowLength = 6 createTileMap(horizontalRowLength, verticalRowLength, tileSize) function moveTiles() for i = #tileTable, 1, -1 do tile = tileTable[i] if tile ~= nil then tile.y = tile.y + 5 if tile.y \> screenH then display.remove( tileTable[i] ) table.remove( tileTable, i ) -- tileTable[i]:removeSelf() -- tileTable[i] = nil end end end end Runtime:addEventListener("enterFrame", moveTiles)

Nice! I’ve actually never used display.remove() before, didn’t know it was there. It solved it thanks !

I think the problem was that you were deleting items before the top of the table. It’s not the display.remove() which helps, but the table.remove()

Essentially, you were deleting, let’s say, item #4 when there were 7 items in your table. That means that items #5, #6 and #7 also get lost because the # method of getting a table’s length only looks up the table until a nil entry is found.

You could have used table.maxn() instead.

A better way to remove display object is not to put them in a table at all but to loop over their parent display group. For example:

local tiles = display.newGroup() local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function createTileMap(horizontalRowLength, verticalRowLength, tileSize) for i = 1, horizontalRowLength do color1 = math.random(0, 1) tile\_Vertical = display.newRect( tiles, 0, 0, tileSize, tileSize ) tile\_Vertical.x = (i - .5) \* tileSize tile\_Vertical.y = screenH - (tileSize\*.5) tile\_Vertical:setFillColor( color1, color1, color1 ) --Fill rows table -- table.insert(tileTable, tile\_Vertical) for b = 1, verticalRowLength do color1 = math.random(0, 1) tile\_Horizontal = display.newRect(0, 0, tileSize, tileSize) tile\_Horizontal.x = tile\_Vertical.x tile\_Horizontal.y = tile\_Vertical.y - (tileSize \* b) tile\_Horizontal:setFillColor( color1, color1, color1 ) --Fill rows table -- table.insert(tileTable, tile\_Horizontal) end end end horizontalRowLength = 7 tileSize = 30 verticalRowLength = 6 createTileMap(horizontalRowLength, verticalRowLength, tileSize) function moveTiles() for i = tiles.numChildren, 1, -1 do tile = tiles[i] if tile ~= nil then tile.y = tile.y + 5 if tile.y \> screenH then display.remove( tiles[i] ) -- table.remove( tileTable, i ) -- tileTable[i]:removeSelf() -- tileTable[i] = nil end end end end Runtime:addEventListener("enterFrame", moveTiles)

Bear in mind that I have not accounted for the tile positions when adding to the group.

Try this:

tileTable = {} local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function createTileMap(horizontalRowLength, verticalRowLength, tileSize) for i = 1, horizontalRowLength do color1 = math.random(0, 1) tile\_Vertical = display.newRect(0, 0, tileSize, tileSize) tile\_Vertical.x = (i - .5) \* tileSize tile\_Vertical.y = screenH - (tileSize\*.5) tile\_Vertical:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Vertical) for b = 1, verticalRowLength do color1 = math.random(0, 1) tile\_Horizontal = display.newRect(0, 0, tileSize, tileSize) tile\_Horizontal.x = tile\_Vertical.x tile\_Horizontal.y = tile\_Vertical.y - (tileSize \* b) tile\_Horizontal:setFillColor( color1, color1, color1 ) --Fill rows table table.insert(tileTable, tile\_Horizontal) end end end horizontalRowLength = 7 tileSize = 30 verticalRowLength = 6 createTileMap(horizontalRowLength, verticalRowLength, tileSize) function moveTiles() for i = #tileTable, 1, -1 do tile = tileTable[i] if tile ~= nil then tile.y = tile.y + 5 if tile.y \> screenH then display.remove( tileTable[i] ) table.remove( tileTable, i ) -- tileTable[i]:removeSelf() -- tileTable[i] = nil end end end end Runtime:addEventListener("enterFrame", moveTiles)

Nice! I’ve actually never used display.remove() before, didn’t know it was there. It solved it thanks !

I think the problem was that you were deleting items before the top of the table. It’s not the display.remove() which helps, but the table.remove()

Essentially, you were deleting, let’s say, item #4 when there were 7 items in your table. That means that items #5, #6 and #7 also get lost because the # method of getting a table’s length only looks up the table until a nil entry is found.

You could have used table.maxn() instead.

A better way to remove display object is not to put them in a table at all but to loop over their parent display group. For example:

local tiles = display.newGroup() local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function createTileMap(horizontalRowLength, verticalRowLength, tileSize) for i = 1, horizontalRowLength do color1 = math.random(0, 1) tile\_Vertical = display.newRect( tiles, 0, 0, tileSize, tileSize ) tile\_Vertical.x = (i - .5) \* tileSize tile\_Vertical.y = screenH - (tileSize\*.5) tile\_Vertical:setFillColor( color1, color1, color1 ) --Fill rows table -- table.insert(tileTable, tile\_Vertical) for b = 1, verticalRowLength do color1 = math.random(0, 1) tile\_Horizontal = display.newRect(0, 0, tileSize, tileSize) tile\_Horizontal.x = tile\_Vertical.x tile\_Horizontal.y = tile\_Vertical.y - (tileSize \* b) tile\_Horizontal:setFillColor( color1, color1, color1 ) --Fill rows table -- table.insert(tileTable, tile\_Horizontal) end end end horizontalRowLength = 7 tileSize = 30 verticalRowLength = 6 createTileMap(horizontalRowLength, verticalRowLength, tileSize) function moveTiles() for i = tiles.numChildren, 1, -1 do tile = tiles[i] if tile ~= nil then tile.y = tile.y + 5 if tile.y \> screenH then display.remove( tiles[i] ) -- table.remove( tileTable, i ) -- tileTable[i]:removeSelf() -- tileTable[i] = nil end end end end Runtime:addEventListener("enterFrame", moveTiles)

Bear in mind that I have not accounted for the tile positions when adding to the group.