Life and Next Level Bonuses - noooway/love2d_arkanoid_tutorial GitHub Wiki

In this part I want to implement two bonuses: one that adds a life and another that allows to finish a level skipping remaining blocks.

First it is necessary to add code to recognize "Life" and "Next Level" bonuses:

function bonuses.bonus_collected( i, bonus, balls, platform )
   .....
   elseif bonuses.is_life( bonus ) then
      .....
   elseif bonuses.is_next_level( bonus ) then
      .....
   end
   .....
end

function bonuses.is_life( single_bonus )
   local col = single_bonus.bonustype % 10
   return ( col == 8 )
end

function bonuses.is_next_level( single_bonus )
   local col = single_bonus.bonustype % 10
   return ( col == 7 )
end

To reaction on "Add Life" bonus it is necessary to increase lives counter in the lives_display table. An appropriate function is implemented as lives_display.add_life(). I call it inside the bonuses.bonus_collected, where currently all other reactions on bonuses are placed. To do this, it is necessary to supply lives_display as an argument to bonus_collected, which requires to pass it all the way down from the game.update through collision-related functions (probably, not an optimal solution).

function game.update( dt )
   .....
   collisions.resolve_collisions( balls, platform,
                                  walls, bricks,
                                  bonuses, lives_display )
   .....
end

function collisions.resolve_collisions( balls, platform,
                                        walls, bricks,
                                        bonuses, lives_display )
   .....
   collisions.platform_bonuses_collision( platform, bonuses,
                                          balls, lives_display )
end

function collisions.platform_bonuses_collision( platform, bonuses,
                                                balls, lives_display )
   .....
      if overlap then
         bonuses.bonus_collected( i, bonus, balls, platform, lives_display )
      end
   .....
end

function bonuses.bonus_collected( i, bonus, balls, platform, lives_display )
   .....
   elseif bonuses.is_life( bonus ) then
      lives_display.add_life()
   elseif
   .....
end

function lives_display.add_life()
   lives_display.lives = lives_display.lives + 1
end

The "Next Level" bonus works the following way: when it is caught, a portal inside the right wall is activated. If the player touches the portal with the platform, transition to the next level occurs.

If the "Next Level" bonus is caught, a special flag in the right wall is activated walls.current_level_walls["right"].next_level_bonus = true. This is done inside the bonuses.bonus_collected function and (again) requires to pass the walls table as an argument through all the collision-related functions.

function collisions.resolve_collisions( balls, platform,
                                        walls, bricks,
                                        bonuses, lives_display )
   .....
   collisions.platform_bonuses_collision( platform, bonuses,
                                          balls, walls,
                                          lives_display )
end

function collisions.platform_bonuses_collision( platform, bonuses,
                                                balls, walls,
                                                lives_display )
   .....
      if overlap then
         bonuses.bonus_collected( i, bonus,
                                  balls, platform,
                                  walls, lives_display )
      end
   .....
end

function bonuses.bonus_collected( i, bonus,
                                  balls, platform,
                                  walls, lives_display )
   .....
   elseif bonuses.is_next_level( bonus ) then
      walls.current_level_walls["right"].next_level_bonus = true
   end
   .....
end

To indicate that a portal to the next level is open, appearance of the wall is changed.

function walls.draw_wall( single_wall )
   .....
   love.graphics.setColor( 255, 0, 0, 100 )
   if single_wall.next_level_bonus then
      love.graphics.setColor( 0, 0, 255, 100 )
   end
   love.graphics.rectangle( 'fill',
                            single_wall.position.x,
                            single_wall.position.y,
                            single_wall.width,
                            single_wall.height )
   .....
end

If the platform touches the right wall, the game switches to the next level. Instead of calling game.switch_to_next_level from collision-resolution functions, it is more convenient to raise a special flag in the platform object and check it each update cycle.

function collisions.platform_walls_collision( platform, walls )
   .....
      if overlap then    
         platform.bounce_from_wall( shift_platform, wall )
      end
   .....
end

function platform.bounce_from_wall( shift_platform, wall )
   platform.position.x = platform.position.x + shift_platform.x
   if wall.next_level_bonus then
      platform.activated_next_level_bonus = true
   end
end

function game.switch_to_next_level( bricks, levels )
   if bricks.no_more_bricks or platform.activated_next_level_bonus then
      .....
   end
end

The effect of the bonus is lost if next level is reached or all the balls are lost.

function game.enter( prev_state, ... )
   .....
   if args and args.current_level then
      .....
      platform.remove_bonuses_effects()
      walls.remove_bonuses_effects()
   end      
end

function game.check_no_more_balls( balls, lives_display )
   if balls.no_more_balls then
       .....
         platform.remove_bonuses_effects()
         walls.remove_bonuses_effects()
       .....
   end
end

function platform.remove_bonuses_effects()
   platform.remove_glued_effect()
   platform.reset_size_to_norm()
   platform.activated_next_level_bonus = false
end

function walls.remove_bonuses_effects()
   walls.current_level_walls["right"].next_level_bonus = false
end