-
Notifications
You must be signed in to change notification settings - Fork 19
Splitting Code Into Several Files
In this part I'm finally going to split the main.lua
into several smaller files.
In Lua, a main program can load external files using require
function.
When a file is require
d, the code inside it is executed.
By default, the execution takes place in the global environment of the main program.
Thus, every variable that is not declared local
, will be visible in the main program.
The local
variables are accessible only from the file, and do not pollute the global environment.
If the external file has a return
statement, that would be the result of the require
statement
in the main program.
Typically, inside the external file a table is created, where all the essential
definitions are added. This table is then return
ed into the main program.
Auxiliary functions and variable are declared local
and are not added to the resulting table.
For demonstration, suppose there is a greetings.lua
file with the following content:
local greetings = {} --(*1)
greetings.hello_message = "Hello from Greetings module."
function greetings.say_hello()
print( greetings.hello_message )
end
local secret = "IDDQD"
function greetings.reveal_secret()
print( secret )
end
function make_mess()
mess = "terrible"
end
return greetings --(*2)
(*1): declaration of the greetings
table, where all the module definitions will be added.
Typically such table is declared local
.
(*2): this table is return
ed at the end of the module.
It is possible to load and test this module from the interpreter:
> greet = require "greetings" --(*1)
> greet.hello_message --(*2)
Hello from Greetings module.
> greet.say_hello() --(*2)
Hello from Greetings module.
> greet.secret --(*3)
nil
> greet.reveal_secret() --(*3)
IDDQD
> mess --(*5)
nil
> greet.make_mess() --(*4)
stdin:1: attempt to call a nil value (field 'make_mess')
stack traceback:
stdin:1: in main chunk
[C]: in ?
> make_mess() --(*4)
> greet.mess --(*5)
nil
> mess --(*5)
terrible
(*1): "greetings" is required. The .lua
extension is omitted. The returned table is
assigned to the greet
variable. For interpreter to be able to find the "greetings.lua",
it has to be launched from the same folder where the file is stored
(*2): both hello_message
and say_hello
are accessible from the greet
table.
(*3): secret
is declared local
and can't be accessed from the interpreter.
However, greet.reveal_secret
function has access to it.
(*4): the make_mess
definition is not prefixed with local
nor with module table.
This function becomes defined in the global namespace.
(*5): mess
variable is initially empty in the global namespace.
After call to make_mess
function, mess
variable
becomes defined in the global scope, not in the greet
table.
With such a simple approach it is necessary to be careful not to accidentally put a declaration
in the global scope. Every declaration should be either local
or go into greetings
table.
I plan to address this issue in the Appendix.
Following this scheme, in the current code it is necessary to move each table in a separate file and add a return statement returning this table.
local levels = {}
levels.current_level = 1
levels.gamefinished = false
levels.sequence = {}
.....
return levels
After that, in the main.lua
it is necessary to require
these files:
local ball = require "ball"
local platform = require "platform"
local bricks = require "bricks"
local walls = require "walls"
local collisions = require "collisions"
local levels = require "levels"
.....
Apart from that, the code rest of the code in the main.lua
doesn't change.
The only thing I want to introduce in this chapter is vector
module from HUMP.
It allows to simplify some arithmetics
local vector = require "vector"
local ball = {}
ball.position = vector( 200, 500 )
ball.speed = vector( 700, 700 )
ball.radius = 10
function ball.update( dt )
ball.position = ball.position + ball.speed * dt
end
function ball.draw()
local segments_in_circle = 16
love.graphics.circle( 'line',
ball.position.x,
ball.position.y,
ball.radius,
segments_in_circle )
end
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: