Skip to content
noooway edited this page Jun 4, 2017 · 19 revisions

In this part, score counter is implemented.

Score is increased on each successful action of the player. This adds another element of interactivity into the game and contributes a bit to player's involvement. To make it more meaningful, lives are added when certain milestones are reached.

From implementation standpoint, score display is similar to lives display, which can be used as a starting point for this object.

local vector = require "vector"

local score_display = {}
score_display.position = vector( 680, 32 )
score_display.score = 0

function score_display.update( dt )
end

function score_display.draw()
   love.graphics.print( "Score: " .. tostring( score_display.score ),
                        score_display.position.x,
                        score_display.position.y )
end

function score_display.reset()
   score_display.score = 0
end

Score is updated each time a brick breaks. 10 points are added for simple brick and 30 for armored.

function score_display.add_score_for_simple_brick()
   score_display.score = score_display.score + 10
end

function score_display.add_score_for_cracked_brick()
   score_display.score = score_display.score + 30
end

In the current code structure, bricks.brick_hit_by_ball function determines whether or not a brick breaks after collision with a ball. The score-increasing functions also have to be called from there.

function bricks.brick_hit_by_ball( i, brick, shift_ball, bonuses, score_display )
   if bricks.is_simple( brick ) then
      .....
      score_display.add_score_for_simple_brick()
      table.remove( bricks.current_level_bricks, i )
      simple_break_sound:play()
   elseif .....
   elseif bricks.is_cracked( brick ) then
      .....
      score_display.add_score_for_cracked_brick()
      table.remove( bricks.current_level_bricks, i )
      armored_break_sound:play()
   elseif bricks.is_heavyarmored( brick ) then
      ball_heavyarmored_sound:play()
   end
end

Just like the lives_display, the score_counter is placed inside the side_panel object.

local lives_display = require "lives_display"
local score_display = require "score_display"

side_panel.lives_display = lives_display
side_panel.score_display = score_display

function side_panel.update( dt )
   side_panel.lives_display.update( dt )
   side_panel.score_display.update( dt )
end

function side_panel.draw()
   side_panel.draw_background()
   side_panel.lives_display.draw()
   side_panel.score_display.draw()
end

function side_panel.reset()
   side_panel.lives_display.reset()
   side_panel.score_display.reset()
end

Care should be taken regarding passing of the side_panel.score_display and side_panel.lives_display into collision-resolving functions.

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

Certain minor modifications to the "game", such as replacement of side_panel.lives_display.reset by side_panel.reset are also necessary.

function game.enter( prev_state, ... )
   .....
   if prev_state == "gameover" or prev_state == "gamefinished" then
      side_panel.reset()
      music:rewind()
   end
   .....
end

To add life on score milestone, it is necessary to compare the current score with the next milestone. While I place a function inside game.update performing such comparison each update cycle, it is probably more efficient to do it immediately after each score change.

function game.update( dt )
   .....
   side_panel.lives_display.add_life_if_score_reached( 
      side_panel.score_display.score )
   game.check_no_more_balls( balls, side_panel.lives_display )
   .....
end

The milestone should be increased each time the previous value is reached. For this reason, it is necessary to keep it's state somehow. I maintain lives_display.lives_added_from_score counter and the next milestone is computed as (lives_display.lives_added_from_score + 1) * 3000, i.e. life is added each 3000 points.

.....
lives_display.lives_added_from_score = 0

function lives_display.add_life_if_score_reached( score )
   local score_milestone = (lives_display.lives_added_from_score + 1) * 3000
   if score >= score_milestone then
      lives_display.add_life()
      lives_display.lives_added_from_score = lives_display.lives_added_from_score + 1
   end
end
   
function lives_display.reset()
   lives_display.lives = 5
   lives_display.lives_added_from_score = 0
end

    Home
    Acknowledgements
    Todo

Chapter 1: Prototype

  1. The Ball, The Brick, The Platform
  2. Game Objects as Lua Tables
  3. Bricks and Walls
  4. Detecting Collisions
  5. Resolving Collisions
  6. Levels

    Appendix A: Storing Levels as Strings
    Appendix B: Optimized Collision Detection (draft)

Chapter 2: General Code Structure

  1. Splitting Code into Several Files
  2. Loading Levels from Files
  3. Straightforward Gamestates
  4. Advanced Gamestates
  5. Basic Tiles
  6. Different Brick Types
  7. Basic Sound
  8. Game Over

    Appendix C: Stricter Modules (draft)
    Appendix D-1: Intro to Classes (draft)
    Appendix D-2: Chapter 2 Using Classes.

Chapter 3 (deprecated): Details

  1. Improved Ball Rebounds
  2. Ball Launch From Platform (Two Objects Moving Together)
  3. Mouse Controls
  4. Spawning Bonuses
  5. Bonus Effects
  6. Glue Bonus
  7. Add New Ball Bonus
  8. Life and Next Level Bonuses
  9. Random Bonuses
  10. Menu Buttons
  11. Wall Tiles
  12. Side Panel
  13. Score
  14. Fonts
  15. More Sounds
  16. Final Screen
  17. Packaging

    Appendix D: GUI Layouts
    Appendix E: Love-release and Love.js

Beyond Programming:

  1. Game Design
  2. Minimal Marketing (draft)
  3. Finding a Team (draft)

Archive

Clone this wiki locally