Bricks and Walls - noooway/love2d_arkanoid_tutorial GitHub Wiki

In Arkanoid bricks are arranged in a 2d-pattern. The next step is to add an array of bricks on the screen and walls to the borders.

The simplest way to create a 2d-pattern is to define several rows and columns of bricks:

bricks.rows = 8
bricks.columns = 11

For each brick we have to provide it's top-left corner position. It can be calculated using it's row and column indices, individual brick's width and height, vertical and horizontal distances between the bricks, and position of the top-left brick relative to the top-left corner of the screen:

local new_brick_position_x = bricks.top_left_position_x + 
   ( col - 1 ) *                                           --(*1)
   ( bricks.brick_width + bricks.horizontal_distance )
local new_brick_position_y = bricks.top_left_position_y + 
   ( row - 1 ) *                                           --(*1)
   ( bricks.brick_height + bricks.vertical_distance )     

(*1): indexing in Lua starts from 1 instead of 0.

When actual values for the parameters are provided, it is possible to populate bricks.current_level_bricks by looping over possible values of the row and column indices:

local bricks = {}
bricks.rows = 8                    --(*1a)
bricks.columns = 11
bricks.top_left_position_x = 70
bricks.top_left_position_y = 50
bricks.brick_width = 50
bricks.brick_height = 30
bricks.horizontal_distance = 10
bricks.vertical_distance = 15      --(*1b)
bricks.current_level_bricks = {}
.....
function bricks.construct_level()
   for row = 1, bricks.rows do
      for col = 1, bricks.columns do
         local new_brick_position_x = bricks.top_left_position_x +   --(*2)
            ( col - 1 ) *
            ( bricks.brick_width + bricks.horizontal_distance )
         local new_brick_position_y = bricks.top_left_position_y +   --(*2)
            ( row - 1 ) *
            ( bricks.brick_height + bricks.vertical_distance )     
         local new_brick = bricks.new_brick( new_brick_position_x,   --(*3)
                                             new_brick_position_y )
         bricks.add_to_current_level_bricks( new_brick )             --(*4)
      end      
   end   
end

(*1a)-(*1b): definition of the properties necessary to compute top left corner position for each brick.
(*2): top left position is computed.
(*3): a new brick is created.
(*4): the new brick is inserted into the bricks table.

In this part, I also want to add the walls on the borders of the screen. A wall is a rectangle, just like a brick is, so I use a walls table which is similar to bricks in it's structure.

There is a minor difference in walls.new_wall constructor: I do not provide a default width and height for the wall:

function walls.new_wall( position_x, position_y, width, height )
   return( { position_x = position_x,
             position_y = position_y,
             width = width,
             height = height } )
end

In walls.construct_walls, the left, right, top and bottom walls are constructed and then manually inserted into the walls.current_level_walls table:

function walls.construct_walls()
   local left_wall = walls.new_wall(
      0,
      0,
      walls.wall_thickness,
      love.graphics.getHeight()
   )
   local right_wall = walls.new_wall(
      love.graphics.getWidth() - walls.wall_thickness,
      0,
      walls.wall_thickness,
      love.graphics.getHeight()
   )
   local top_wall = walls.new_wall(
      0,
      0,
      love.graphics.getWidth(),
      walls.wall_thickness
   )
   local bottom_wall = walls.new_wall(
      0,
      love.graphics.getHeight() - walls.wall_thickness,
      love.graphics.getWidth(),
      walls.wall_thickness
   ) 
   walls.current_level_walls["left"] = left_wall
   walls.current_level_walls["right"] = right_wall
   walls.current_level_walls["top"] = top_wall
   walls.current_level_walls["bottom"] = bottom_wall
end

Constructors for the walls and the bricks have to be placed in love.load, so the walls and the bricks are created on the start of the game:

function love.load()
   bricks.construct_level()
   walls.construct_walls()
end

Finally, the love.update and love.draw functions now look like:

function love.update( dt )
   ball.update( dt )
   platform.update( dt )
   bricks.update( dt )
   walls.update( dt )
end
 
function love.draw()
   ball.draw()
   platform.draw()
   bricks.draw()
   walls.draw()
end