Collision Handling in Breakout Clone

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
gyps
Prole
Posts: 1
Joined: Sat Mar 23, 2019 11:26 pm

Collision Handling in Breakout Clone

Post by gyps »

Hey everyone,
I'm pretty new to LÖVE (and gamedev in general), and have been trying to make a Breakout/Brick Breaker style game, but I've run into some problems with making the ball bounce off the blocks. My current code works for the most part, but I assume there's a much more efficient/idiomatic way to handle this, and currently when the ball hits two blocks at once it just goes right through them, which isn't exactly what I intended. If anyone has any tips it would be greatly appreciated.

Here's the collision handling code in my 'play' gamestate:

Code: Select all

local loop = true
for x = 0, blocks.columns - 1 do -- Iterate through block array columns
  for y = 0, blocks.rows - 1 do -- Iterate through block array rows
    local currentBlock = blocks.array[x][y]

    -- Blocks deactivate and reflect ball when they get hit
    if ball:collides(currentBlock) and currentBlock.active then
      currentBlock.active = false
      blockCount = blockCount - 1

      if ball:xAxisCollides(currentBlock) then
        ball.dy = -ball.dy
        loop = false
        break
      else
        ball.dx = -ball.dx
        loop = false
      end
    end

    if not loop then break end
  end
end
and here are the methods that the previous code is calling (this is in my 'ball' class):

Code: Select all

function Ball:collides(object)
  if self.x > object.x + object.width or object.x > self.x + self.width then
    return false
  elseif self.y > object.y + object.height or object.y > self.y + self.height then
      return false
  else
    return true
  end
end


function Ball:xAxisCollides(object)
  local ballCenter = {self.x + self.width / 2, self.y + self.height / 2}

  local objectCenter = {object.x + object.width / 2, object.y + object.height / 2}

  local distanceX = math.sqrt((ballCenter[1] - objectCenter[1]) ^ 2) / object.width
  local distanceY = math.sqrt((ballCenter[2] - objectCenter[2]) ^ 2) / object.height

  if distanceY > distanceX then
    return true
  else
    return false
  end
end
I'd be happy to provide a .love file if need be, but I'm guessing that's probably overkill for a problem like this. Thanks in advance, I really appreciate the help!
tobiasvl
Prole
Posts: 29
Joined: Mon Oct 01, 2018 4:58 pm
Location: Norway
Contact:

Re: Collision Handling in Breakout Clone

Post by tobiasvl »

I don't know exactly why you're having collision problems, but I can point out some inefficient and non-idiomatic things.

In your first code block, you loop through all the blocks to see if any of them happen to be hit by a ball at the moment.

First of all, it's not idiomatic at all to start Lua tables at index 0, although it is in other languages. In Lua, the equivalent to an array is called a sequence, and it is a special table (or part of a table) where the index starts at 1, and until the first numbered index that is nil. These sequences can be iterated over with the ipairs() function.

You can of course also iterate over them the way you do, with a regular for loop with a numerical index, but if you're using a proper sequence you don't need to keep track of the number of columns and rows yourself, you can just use the # operator to get the length of the sequence.

That said, it's not very efficient to iterate over all blocks until you maybe find one that is hit. Instead, you should look up the ball's x and y coordinates and see if there is a block there. You already have code that does this check, so I don't really understand why you don't just apply it directly instead of looping through all blocks first. You have to divide the actual x and y pixel coordinates by the width and height of the blocks (and add an offset, probably) to translate the pixel coordinates to block columns and rows, but that'll probably be faster.
monkyyy
Citizen
Posts: 52
Joined: Fri Mar 16, 2012 5:29 pm

Re: Collision Handling in Breakout Clone

Post by monkyyy »

Your code seems verbose to me, why do you have a 2d block arrey with object like code?
Please just use Lua style 1 starts.

I would just teleport the block a frame backwards after a collision.

Code: Select all

if collision then 
ball.x = ball.x - ball.xv
Ball.y = ball.y - ball.yv
If magic collision logic then ball.xv = -ball.xv else ball.yv = -ball.yv
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 47 guests