Brick Breaker with physics

I am in the beginning stages of creating a brick breaker style game and am running into an issue when removing physics objects from my table. I give all my physics objects an attribute called index and when a collision occurs I access that index to remove the correct object. I assumed this would work but I receive an error in my for loop that iterates through my table of objects. Any input on this would be appreciated.

-- Brick Breaker

-- Use this function to perform your initial setup
function setup()
   --displayMode(FULLSCREEN)
   rectMode(CENTER)
   print("Hello World!")
   bricks = {}
   floor = physics.body(EDGE, vec2(0,0), vec2(WIDTH, 0))
   rightWall = physics.body(EDGE, vec2(WIDTH, 0), vec2(WIDTH, HEIGHT))
   leftWall = physics.body(EDGE, vec2(0,0), vec2(0, HEIGHT))
   TopScreen = physics.body(EDGE, vec2(0, HEIGHT), vec2(WIDTH, HEIGHT))
   floor.restitution = 1
   rightWall.restitution = 1
   TopScreen.restitution = 1
   leftWall.restitution = 1
   paddleWidth = 100
   paddleHeight = 25
   paddle = physics.body(POLYGON,
   vec2(-paddleWidth/2, -paddleHeight/2), --bottom left
   vec2(-paddleWidth/2, paddleHeight/2),
   vec2(paddleWidth/2, paddleHeight/2),
   vec2(paddleWidth/2, -paddleHeight/2)

   )
   paddle.x = WIDTH/2
   paddle.y = 100
   paddle.type = STATIC
   paddle.restitution = 1


   ball = physics.body(CIRCLE, 25)
   ball.x = WIDTH/2
   ball.y = HEIGHT/2-200
   ball.restition = 1
   ball.gravityScale = 0
   ball:applyForce(vec2(0, -3000))
   index = 0
   for i = 0, 6 do
       spawnBrick(100*i, HEIGHT-(100), i)
   end


end

-- This function gets called once every frame
function draw()
   -- This sets a dark background color
   background(40, 40, 50)

   -- This sets the line thickness
   strokeWidth(5)




   -- Do your drawing here
   ellipse(ball.x, ball.y, 50)
   paddle.x = paddle.x + Gravity.x * 5


   pushMatrix()
   translate(paddle.x, paddle.y)
   rotate(paddle.angle)
   rect(0, 0, paddleWidth, paddleHeight)
   popMatrix()
   for i, brick in ipairs(bricks) do
       rect(brick.x, brick.y, brickWidth, brickHeight)
   end
end

function spawnBrick(x, y, i)
   brickWidth = 100
   brickHeight = 50
   brick = physics.body(POLYGON,
   vec2(-brickWidth/2, -brickHeight/2), --bottom left
   vec2(-brickWidth/2, brickHeight/2),
   vec2(brickWidth/2, brickHeight/2),
   vec2(brickWidth/2, -brickHeight/2)

   )
   brick.x = x
   brick.y = y
   brick.type = STATIC
   brick.restitution = 1
   brick.info = "brick"
   brick.index = i
   table.insert(bricks, brick)
end

function collide(contact)

   if contact.state == ENDED then
       if contact.bodyA ~= nil then
           if contact.bodyA.info == "brick" then
                print(contact.bodyA.index)
                table.remove(bricks, contact.bodyA.index)
                contact.bodyA:destroy()
           end
       end
   end
end

@dkharley That’s usually caused because you’re in the middle of a loop and something is removed from the table the loop is doing. You should set a flag on the item being deleted and then remove that item by going thru the table in reverse order.

@dkharley I made these changes.

I added this to the end of the draw function.


    for i=#bricks,1,-1 do
        if bricks[i].info=="delete" then
            bricks[i]:destroy()
            table.remove(bricks,i)           
        end
    end

I changed the collide function to this.


function collide(contact)
   if contact.state == ENDED then
       if contact.bodyA ~= nil then
           if contact.bodyA.info == "brick" then
                print(contact.bodyA.index)
                contact.bodyA.info="delete"
           end
       end
   end
end

Awesome thanks for the help. Should I always use this technique when removing items from a table? For example I have a project in which a cloud creates raindrops that eventually fall off screen. When they are below a certain threshold I remove them from the table, when I do this there is usually a flicker that happens to the other raindrops. I assume this is because I am deleting rain drops in the middle of a loop?

@dkharley That usually causes a flicker. When you delete something in the middle of a table, everything else shifts down one position. Then on the next iteration of the table, the first item that got shifted down gets skipped. Sometimes you’ll get a flicker, sometimes you’ll get an error. it all depends on what you’re doing while in the loop. By going in reverse order, you don’t have that problem.