-
Notifications
You must be signed in to change notification settings - Fork 17
Levels
The next step is to implement different levels.
All levels-related information will be held at the levels
table.
The actual sequence of levels will be stored in the levels.sequence
array.
local levels = {}
.....
levels.sequence = {}
I represent each level as a 2d-table. Inner tables correspond to the rows of the bricks. In the future, the numbers will indicate the brick types; currently they only show whether the brick is present on certain position or not.
levels.sequence[1] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1 },
{ 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0 },
{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0 },
{ 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
}
levels.sequence[2] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0 },
{ 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
}
Since there are several levels, it is necessary to maintain the current level number:
levels.current_level = 1
Changes are necessary in bricks.construct_level
function, to make it
receive one of the levels.sequence[.....]
tables with bricks arrangement.
function bricks.construct_level( level_bricks_arrangement )
bricks.no_more_bricks = false
for row_index, row in ipairs( level_bricks_arrangement ) do --(*1)
for col_index, bricktype in ipairs( row ) do
if bricktype ~= 0 then --(*2)
local new_brick_position_x = bricks.top_left_position_x +
( col_index - 1 ) *
( bricks.brick_width + bricks.horizontal_distance )
local new_brick_position_y = bricks.top_left_position_y +
( row_index - 1 ) *
( bricks.brick_height + bricks.vertical_distance )
local new_brick = bricks.new_brick( new_brick_position_x,
new_brick_position_y )
table.insert( bricks.current_level_bricks, new_brick )
end
end
end
end
(*1): Instead of the fixed number of rows and columns, the iteration goes
over the elements of the level_bricks_arrangement
.
(*2): The brick is created if it's type is nonzero.
When there are no more bricks left, switch to the next level happens.
The number of remaining bricks is monitored by bricks.update
function.
If there are none, a function to switch to the next level could be called.
However, instead of that, I raise the bricks.no_more_bricks
flag, which
is checked each update cycle
function bricks.update( dt )
if #bricks.current_level_bricks == 0 then --(*1)
bricks.no_more_bricks = true
else
for _, brick in pairs( bricks.current_level_bricks ) do
bricks.update_brick( brick )
end
end
end
function love.update( dt )
.....
levels.switch_to_next_level( bricks )
end
(*1): The number of remaining bricks is equivalent to the length of the bricks.current_level_bricks
table.
If it is on, then the current_level
is updated,
the new set of bricks is constructed and the ball is repositioned.
function levels.switch_to_next_level( bricks )
if bricks.no_more_bricks then
.....
levels.current_level = levels.current_level + 1
bricks.construct_level( levels.sequence[levels.current_level] )
ball.reposition()
.....
end
end
end
function ball.reposition()
ball.position_x = 200
ball.position_y = 500
end
It is possible to directly call the levels.switch_to_next_level
in the bricks.update
instead of rising the bricks.no_more_bricks
flag.
However, the flag will be more convenient later, when gamestates are introduced.
It is also necessary to do something special when there are no more levels, i.e. when the game is finished. For now, displaying a simple congratulations message should be sufficient.
The total number of levels equals to the length of the levels.sequence
array.
It is possible to check whether the levels.current_level
is the last one by comparing
it with the #levels.sequence
. When there are no more levels left,
switch_to_next_level
function raises the levels.gamefinished
flag.
function levels.switch_to_next_level( bricks )
if bricks.no_more_bricks then
if levels.current_level < #levels.sequence then --(*1)
levels.current_level = levels.current_level + 1 --(*2)
bricks.construct_level( levels.sequence[levels.current_level] )
ball.reposition()
else
levels.gamefinished = true --(*3)
end
end
end
(*1): checks, whether the levels.current_level
is the last one.
(*2): if not, update the level counter, construct new level and reposition the ball.
(*3): otherwise signal that the game is finished.
When levels.gamefinished
is on, the message is displayed
function love.draw()
.....
walls.draw()
if levels.gamefinished then
love.graphics.printf( "Congratulations!\n" ..
"You have finished the game!",
300, 250, 200, "center" )
end
end
Through this tutorial I've chosen to represent levels as 2d Lua tables. In the appendix A a method to store them as text strings is demonstrated.
← 1.5-Resolving Collisions
↑ To the top
Next section: 2.1-Splitting Code Into Several Files →
Feedback is crucial to improve the tutorial!
Let me know if you have any questions, critique, suggestions or just any other ideas.
Chapter 1: Prototype
- The Ball, The Brick, The Platform
- Game Objects as Lua Tables
- Bricks and Walls
- Detecting Collisions
- Resolving Collisions
- Levels
Appendix A: Storing Levels as Strings
Appendix B: Optimized Collision Detection (draft)
Chapter 2: General Code Structure
- Splitting Code into Several Files
- Loading Levels from Files
- Straightforward Gamestates
- Advanced Gamestates
- Basic Tiles
- Different Brick Types
- Basic Sound
- 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
- Improved Ball Rebounds
- Ball Launch From Platform (Two Objects Moving Together)
- Mouse Controls
- Spawning Bonuses
- Bonus Effects
- Glue Bonus
- Add New Ball Bonus
- Life and Next Level Bonuses
- Random Bonuses
- Menu Buttons
- Wall Tiles
- Side Panel
- Score
- Fonts
- More Sounds
- Final Screen
- Packaging
Appendix D: GUI Layouts
Appendix E: Love-release and Love.js
Beyond Programming: