Help with collision

@Paul123 In your above code, you created a table called tiles where you put 10 vec2 values for the boxes. In the below code that you had in draw(), you don’t need to recalculate the box x,y values. You should get their x,y values from the table. Also, you can go thru the tiles table and compare each box x,y value to the position of the ball. If the ball x,y is close to each box x,y , then you can say the ball collided with that box.

    for box=1,10 do -- draw first row of boxes
         sprite("Cargo Bot:Crate Green 1",275+box*42,600)
    end

Thanks Dave, I think I’ve been improving my code, I got the table to store the tiles and display them now!! But I am struggling to use the tables to remove a tile when hit.

It does remove the box but instantly gives an error that I don’t understand and even googling it, I don’t understand. Here is my new code for a look :slight_smile:

-- Break

-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    xpos=512
    ballx=512
    bally=450
    e1=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
    e2=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
    e3=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    ball_diam=30
    p_ball = physics.body(CIRCLE,ball_diam/2) 
    p_ball.gravityScale = 1 
    p_ball.restitution = .8 
    p_ball.friction = 0 
    p_ball.linearVelocity = vec2(math.random(400),math.random(400))  
    p_ball.x = math.random(75,150) 
    p_ball.y = math.random(450,650)
    --add bat
    bat=physics.body(EDGE,vec2(-70,109),vec2(70,109))
    bat.gravityScale = 1 
    bat.restitution = 1.2
    bat.friction = 0 
    -- configure boxes
    tiles={}
    for box = 1, 10 do
      table.insert(tiles,vec2(275+box*42,600))
    end
end

function draw()
      -- define screen space and add collision detection
    strokeWidth(5)
    background(40,40,50)
    color(255)
    line(0,0,0,HEIGHT) -- draw left wall
    line(0,HEIGHT,WIDTH,HEIGHT) -- draw top wall
    line(WIDTH,0,WIDTH,HEIGHT) -- draw right wall

      -- set bat screen limits and collision
    xpos=CurrentTouch.x
    if xpos<=77 then xpos=78
     elseif xpos>=948 then xpos=945
    end
    bat.x=xpos 
    sprite("Planet Cute:Plain Block",xpos,100,150,55) -- bat
      -- add ball and move towards bat
    sprite("Tyrian Remastered:Explosion Ball",p_ball.x,p_ball.y,30,30) -- ball
    if p_ball.y <= 75 then
        text("Ball Lost",350,350) -- placeholder for lost ball
    end
    for box=1,10 do -- draw first row of boxes
    sprite("Cargo Bot:Crate Green 1",tiles[box].x,tiles[box].y)
    end
    -- box collision and removal
      if p_ball.x >= tiles[1].x and p_ball.y >= tiles[1].y then 
        table.remove(tiles,1)
    end
end

@Paul123 When you remove a tile, it’s no longer in the table. That means that instead of 10 tiles, you now have 9, but you’re still trying to look for 10. That’s what’s giving you the error, trying to use a tile that’s not there. To know how many entries are in a table, use the #. So the “for” loop should be " for box = 1, #tiles do". An even better loop would be “for a,b in pairs(tiles) do” then you would use b.x and b.y . The “pairs” knows the size of the table. The “a,b” are just variables. The “a” is the entry offset ( 1,2,3,4,5, etc) and the “b” is the values at that offset. Since you used a vec2 to store 2 values, to get those values you would use .x and .y . So it would be “b.x” and “b.y” . If you used a vec4, you would use .x, .y, .z, .w, so it would be b.x, b.y, b.z, b.w .

You’re quick Dave thank you. You know I kinda figured the problem was because of 9 tiles and the loop did 10 but couldn’t figure out how to fix it. (I did try) Thank you, I’m going to work on it now.

Edit:- I don’t know how you guys write code because to me it’s so so slow and for every 1 step I go forward with my game, I then take 10 steps backwards getting errors and trying to get it working. So with all the time spend fixing and rewriting code, I’m amazed anyone every does anything.

Been working on my box removal code, after 4-5 tries, I did this

   -- box collision and removal
    for t=1,#tiles do
      if p_ball.x >= tiles[t].x and p_ball.x <= tiles[t].x+42 and p_ball.y>=tiles[t].y and p_ball.y<=tiles[t].y+42 then 
        table.remove(tiles,t)
        end
    end

Which to me should work, but when the ball collides I get the error:-

Attempt to index field (a nil value)?

I’m trying to keep positive and motivated but it’s Goddamn hard when you get one small progression every 2 days at the most.

@Paul123, you could draw the tiles and check for collisions with just one loop, like so:

    for id, tile in pairs(tiles) do    -- Loops through table, id is the place in the table and tile holds the data stored there
        sprite("Cargo Bot:Crate Green 1", tile.x, tile.y)    -- Draw a sprite there
        
        -- Collision detection
        if p_ball.x >= tile.x - 21 and p_ball.x <= tile.x + 21 
        and p_ball.y >= tile.y - 21 and p_ball.y <= tile.y + 21 then 
            table.remove(tiles, id) -- If collided, remove tile
        end
    end

P.S. Add this p_ball.linearVelocity = -p_ball.linearVelocity under the table.remove and the ball will reverse direction when it collides, essentially bouncing off.

@Paul123 Things are slow at first, but the more mistakes you make, the more they will help you to avoid them later on. And the more mistakes you know how to avoid, the faster you’ll code. So it’s good to learn from your own mistakes.

Thanks Jak and Dave. I’m making good progress today and I’m quite pleased. Now got 4 rows of tiles 2 diff sizes, also changed the ball from a sprite to an ellipse, didn’t like the sprite. Added scoring and Also added a little damping to try to tone down the rebounds as it’s getting really fast.

No problems atm be which is a major plus, I’m now trying to figure out how to give a slight random variation to the ball direction when it hits the bat because sometimes the ball just goes up and down like mad with no sideways movement.

Here is my code! You think it’s getting decent?

-- Break

-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    xpos=512
    e1=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
    e2=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
    e3=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    ball_diam=30
    p_ball = physics.body(CIRCLE,ball_diam/2) 
    p_ball.gravityScale = .85
    p_ball.restitution = .75
    p_ball.friction = 0.1
    p_ball.linearVelocity = vec2(math.random(150),math.random(225))  
    p_ball.x = 375
    p_ball.y = 300
    p_ball.linearDamping=.25
    score=0
    gamestate=0 -- Game State (0 - Wait to start) (1 - In Play) (2 - Game Over & Show Score)
    --add bat
    bat=physics.body(EDGE,vec2(-70,109),vec2(70,109))
    bat.gravityScale = 1 
    bat.restitution = 1.65 --1.4
    bat.friction = 0 
    -- configure boxes
    tiles={}
    tiles2={}
    tiles3={}
    tiles4={}
    for box = 1, 10 do
      table.insert(tiles,vec2(275+box*42,600))
      table.insert(tiles2,vec2(275+box*42,558))    
    end
    for box=1,12 do
        table.insert(tiles3,vec2(233+box*42,516))
        table.insert(tiles4,vec2(233+box*42,473))
    end
end

function draw()
      -- define screen space and add collision detection
    strokeWidth(5)
    background(40,40,50)
    color(255)
        text("Score:",WIDTH-100,HEIGHT-50)
        text(score,WIDTH-65,HEIGHT-50)
    line(0,0,0,HEIGHT) -- draw left wall
    line(0,HEIGHT,WIDTH,HEIGHT) -- draw top wall
    line(WIDTH,0,WIDTH,HEIGHT) -- draw right wall

      -- set bat screen limits and collision
    xpos=CurrentTouch.x
    if xpos<=77 then xpos=78
     elseif xpos>=948 then xpos=945
    end
    bat.x=xpos 
    sprite("Planet Cute:Plain Block",xpos,100,150,55) -- bat
      -- add ball and move towards bat
    fill(255,0,0)
    ellipse(p_ball.x,p_ball.y,30) -- ball
    if p_ball.y <= 75 then
        text("Ball Lost",350,350) -- placeholder for lost ball
    end
 --   for box=1,#tiles do -- draw first row of boxes
--    sprite("Cargo Bot:Crate Green 1",tiles[box].x,tiles[box].y)
--    end
    -- box collision and removal
    for id, tile in pairs(tiles) do    -- Loops through table, id is the place in the table and tile holds the data stored there
        sprite("Cargo Bot:Crate Green 1", tile.x, tile.y)    -- Draw a sprite there
        -- Collision detection
        if p_ball.x >= tile.x - 21 and p_ball.x <= tile.x + 21 
        and p_ball.y >= tile.y - 21 and p_ball.y <= tile.y + 21 then 
            table.remove(tiles, id) -- If collided, remove tile
        p_ball.linearVelocity = -p_ball.linearVelocity
        score = score + 20
        end
    end
   for id, tile in pairs(tiles2) do    -- Loops through table, id is the place in the table and tile holds the data stored there
        sprite("Cargo Bot:Crate Blue 1", tile.x, tile.y)    -- Draw a sprite there
        -- Collision detection
        if p_ball.x >= tile.x - 21 and p_ball.x <= tile.x + 21 
        and p_ball.y >= tile.y - 21 and p_ball.y <= tile.y + 21 then 
            table.remove(tiles2, id) -- If collided, remove tile
        p_ball.linearVelocity = -p_ball.linearVelocity
        score = score + 20
        end
    end   
   for id, tile in pairs(tiles3) do    -- Loops through table, id is the place in the table and tile holds the data stored there
        sprite("Cargo Bot:Crate Red 1", tile.x, tile.y)    -- Draw a sprite there
        -- Collision detection
        if p_ball.x >= tile.x - 21 and p_ball.x <= tile.x + 21 
        and p_ball.y >= tile.y - 21 and p_ball.y <= tile.y + 21 then 
            table.remove(tiles3, id) -- If collided, remove tile
        p_ball.linearVelocity = -p_ball.linearVelocity
        score = score + 10
        end
    end   
   for id, tile in pairs(tiles4) do    -- Loops through table, id is the place in the table and tile holds the data stored there
        sprite("Cargo Bot:Crate Yellow 1", tile.x, tile.y)    -- Draw a sprite there
        -- Collision detection
        if p_ball.x >= tile.x - 21 and p_ball.x <= tile.x + 21 
        and p_ball.y >= tile.y - 21 and p_ball.y <= tile.y + 21 then 
            table.remove(tiles4, id) -- If collided, remove tile
        p_ball.linearVelocity = -p_ball.linearVelocity
        score = score + 10
        end
    end       
end

function waiting()
    -- Placeholder for Gamestate 0 (Press to play)
end

function showscore()
    -- Placeholder for Gamestate 2 (Game Over & Show Score)
end

@Paul123 Here’s one thing you can do with the bat. You can give the center area of the bat a flat surface and then have it slope from the center area to the edges. That way it will bounce to the right or left if it doesn’t hit the bat in the middle.

Thanks dave1707. Good idea but I don’t think I want a sloped bat. I’ll keep trying diff ideas.

@Paul123, I think Dave meant you could build the physics body like that, but still just draw a normal rectangle.

Also, you could store all the tiles in one 2D table, or even a 1D table if you just store the x and y positions. Either way, there is no need for 4 tables

@JakAttak Yes, that’s what I meant. @Paul123 Maybe one thing you can do with the bat is tilt it a little in the direction it’s moving. If it’s stopped, then make it level. So depending on how the bat is moving will depend on how the ball will bounce.

Thanks Jak.

Good info, I’ll look into it but this is my first try with doing tables. Baby steps :slight_smile:

Hi, I have been looking and searching but I’m still stuck on a couple of things.

1: how to limit the p_ball.linearVelocity speed, so the ball doesn’t get too fast

I tried using damping but it’s very hard to get right because if you set it so it slows the ball down when it’s fast, then when the ball is slow it’s almost stopped.

2: how to deflect the ball at a slight angle when it hits the bat to stop it from getting stuck in a straight up-down loop.

(I am trying to use dave1707s idea for #2, but I’m still stuck with #1)

Edit:- scrub #2, I used Dave’s idea to angle the edge of the bat, I switched to using two physics lines each 50% width and gave it a 5-6 pixel slope. Seems much better. :slight_smile:

Still cannot work out how to slow the ball down so it doesn’t get too fast, I figues its something really simple but I don’t know.

Tried silly things like if p_ball.linearVelocity>=300 then p_ball.linearVelocity=300 but it doesn’t work.

Sorry guys but I still can’t work out how to slow down my ball or limit it’s speed. Right now it gets so fast that it’s impossible to hit. :frowning:

Add gravity or friction.

I got both :frowning:

Apply force in the opposite direction?

I wouldn’t be using physics for breakout, I would just write my own ball and physics and collision code… physics wasn’t designed for no gravity, or a specific speed, and breakout is.

Thats cool SkyTheCoder but I’m a total beginner and this is my first game in codea.

so I wouldnt know how.