DevBlog #2 : Setting Up A Simple Project Using LuaPreprocess
UPDATE
You can now use the love2d-template to easily setup the project (but a little modification is still needed if you want)
I suggest you read the previous post for context here before continuing.
For this post, we are going to continue and learn how to use the awesome Luapreprocess library by setting up a simple LOVE game project.
The purpose of this is to show how I use and setup my project with luapreprocessing as a tool.
(NOTE: I am using Linux so mostly are commands.)
STEP #1 - Setting up the base folder
- Open a terminal.
- Go to your project folder with
cd $HOME/Projects/
- Create the folder
SimpleGame
withmkdir SimpleGame
. - Go to the newly created folder with
cd SimpleGame
. (Remember this is the base project directory) - Create the following file:
Makefile
andhandler.lua
withtouch Makefile handler.lua
- Create a the
simplegame
folder withmkdir simplegame
- Create the folder
modules
andassets
withmkdir modules assets
- Clone the
Luapreprocess
repository usinggit clone https://github.com/ReFreezed/LuaPreprocess luapreprocess
- List the contents of the current folder you are in with the command
ls
. You should see the following:handler.lua Makefile assets/ modules/ luapreprocess/ simplegame/
OPTIONAL:
- If you are going to use submodules (lua/love libraries), you have to
git submodule add
from the base project directory. For example:git submodule add https://github.com/flamendless/log.lua modules/log
git submodule add https://github.com/rxi/classic modules/classic
STEP #2 - Creating the Makefile
(UPDATE: See this post for a better build system)
- Now open
Makefile
with your favourite text editor. In my case I usevim
so the command isvim Makefile
. - Type/paste the following: ( I will put comment for explanations, comments in Makefile is the string after the syntax
#
)define search #(1 path, 2 pattern) -> list $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call search,$d/,$2)) endef # the following are the variables we are going to use PROJECT_NAME := simplegame # this is the same OUTPUT_DIRECTORY := output # this is where all the preprocessed lua files will go. # this is important because the modules folder will contain other lua libraries # which usually containes examples and test folders. Preprocessing those will lead to errors. EXCLUDES := modules # the following will contain the list of lua files that are going to be preprocessed # NOTE: follow the whitespaces carefully. # extra whitespace inside the parenthesis will affect the result of the commands SOURCE_PATH := ./$(PROJECT_NAME) SOURCE_FILES := $(strip $(call search,$(SOURCE_PATH),*.lua2p)) SOURCE_OBJECTS := $(SOURCE_FILES:$(SOURCE_PATH)/%.lua2p=./$(OUTPUT_DIRECTORY)/%.lua) # this variable will hold the folders to be copied to the output directory # they are usually the dependencies of your program DIRECTORIES_TO_COPY := ecs assets states objects # these are the folders that are also in the root project directory MODULES_DIR = modules ASSETS_DIR = assets # this variable is the path to the LuaPreprocess library, mainly the command line version of the library LPP_PATH := ./luapreprocess/preprocess-cl.lua # these are the recipes to be run when we run make # NOTE: there should be a "tab" in the body of the recipe process: init $(SOURCE_OBJECTS) @echo preprocessing finished # just print something love $(OUTPUT_DIRECTORY) # this will launch the game after preprocessing # this recipe is where the magic happens ./$(OUTPUT_DIRECTORY)/%.lua: ./$(PROJECT_NAME)/%.lua2p @echo processing input: $< # print the current lua2p file to be processed @echo processing output: $@ # print the preprocessed lua2p file, now a lua file # this will run the command to preprocess the current file # using the handler.lua (variable definitions), and output them accordingly lua $(LPP_PATH) --hander=handler.lua --outputpaths $< $@ # this recipe is the initializer: # create the OUTPUT_DIRECTORY if it does not exist # copy the DIRECTORIES_TO_COPY to the OUTPUT_DIRECTORY if does not exist # NOTE, the whitespace inside the brackets are necessary # NOTE, the \ is also important, they allow multiple lines init: @if [ ! -d $(OUTPUT_DIRECTORY) ]; \ then mkdir -p $(OUTPUT_DIRECTORY); \ else \ echo "$(OUTPUT_DIRECTORY) directory already exists"; \ fi @for x ($(DIRECTORIES_TO_COPY)); do \ if [ ! -d $(OUTPUT_DIRECTORY)/$$x ]; then \ cp -rf $(PROJECT_NAME)/$$x $(OUTPUT_DIRECTORY)/; \ else \ echo "$$x already exists"; \ fi; \ done @if [ ! -d $(OUTPUT_DIRECTORY)/$(DIR_MODULES) ]; then \ cp -rf $(DIR_MODULES) $(OUTPUT_DIRECTORY)/; \ else \ echo "$(DIR_MODULES) already exists in $(OUTPUT_DIRECTORY)"; \ fi @if [ ! -d $(OUTPUT_DIRECTORY)/$(DIR_ASSETS) ]; then \ cp -rf $(DIR_ASSETS) $(OUTPUT_DIRECTORY)/; \ else \ echo "$(DIR_ASSETS) already exists in $(OUTPUT_DIRECTORY)"; \ fi # this recipe will clean the output folder, necessary for rebuilding the project clean: @if [ -d $(OUTPUT_DIRECTORY) ]; then \ rm -rf $(OUTPUT_DIRECTORY); \ else \ echo "$(OUTPUT_DIRECTORY) directory does not exist"; \ fi
- Take a break. Drink water.
STEP #3 - Creating the handler.lua
- Now open
handler.lua
with your favourite text editor. In my case I usevim
so the command isvim handler.lua
. - Type/paste the following:
_DEBUG = true _GAME_TITLE = "Simple Game" _GAME_SIZE = { x = 1024, y = 512 } return {} --this is needed according to the developer of Luapreprocess
- Save and exit the file.
STEP #4 - Creating the SimpleGame
- Go to the
simplegame
folder withcd simplegame
- Create the following files: main.lua2p and conf.lua2p with
touch main.lua2p conf.lua2p
(Note: You need to use the extensionlua2p
instead oflua
for your files inside thesimplegame
directory.) - Open
conf.lua2p
with your text editor and type/paste the following:function love.conf(t) --Remember, _GAME_NAME and _GAME_SIZE are defined in the handler.lua file local title = !(_GAME_TITLE) --this is how to use the luapreprocessor as a one-liner local size = !(_GAME_SIZE) --_GAME_SIZE is a table as defined in the handler.lua file t.window.title = title t.window.width = size.x t.window.height = size.y end
- Save and exit the
conf.lua2p
file. - Now open the
main.lua2p
file, we are going to show just a simple rectangle on the screen. Also, if the_DEBUG
variable in thehandler.lua
file istrue
we will show a text, iffalse
we will show not show the text. Type/paste the following:function love.draw() love.graphics.setColor(1, 1, 1, 1) love.graphics.rectangle("fill", 64, 6, 128, 128) --mind the ! syntax !if _DEBUG then love.graphics.print("_DEBUG is true!", 8, 8) !end end
STEP #5 - Running the game
Now here is the moment of truth, make sure you are in the base project directory. To check, run the command pwd
, you should NOT see $HOME/Projects/SimpleGame/simplegame
, rather it should be $HOME/Projects/SimpleGame
- Run
make init
- Run
make
. It should launch the game. You should see a printed text in the top-left corner of the game.
STEP #5.5 - Analyzing
To know what just happened, look at the main.lua
and conf.lua
files inside the output
folder, you should see: (P.S. the comments are not to be regarded)
--in conf.lua file
function love.conf(t)
local title = "Simple Game"
local size = {x=1024,y=512}
t.window.title = title
t.window.width = size.x
t.window.height = size.y
end
--in main.lua file
function love.draw()
love.graphics.setColor(1, 1, 1, 1)
love.graphics.rectangle("fill", 64, 6, 128, 128)
love.graphics.print("_DEBUG is true!", 8, 8)
end
STEP #6 - Testing the LuaPreprocess
Now, let us test and see the output if we turn off the _DEBUG
variable in handler.lua
. To do that, just change _DEBUG = true
to _DEBUG = false
- Run
make
again, you should NOT see any printed line at the top-left corner of the game.
Now open the main.lua
file in the output
folder. You should see:
function love.draw()
love.graphics.setColor(1, 1, 1, 1)
love.graphics.rectangle("fill", 64, 6, 128, 128)
end
See? The line inside the !if _DEBUG
and !end
is gone.
Do you now know why preprocessing is good? This will be the case if we DO NOT use preprocessing:
--in main.lua
_DEBUG = true --a global variable
function love.draw()
love.graphics.setColor(1, 1, 1, 1)
love.graphics.rectangle("fill", 64, 6, 128, 128)
--this is an extra check!
--extra check = extra memory access and extra processing
--extra lines of code = extra filesize
if _DEBUG then
love.graphics.print("_DEBUG is true!", 8, 8)
end
end
I hope you understand and followed through this guide. Next blog post will be about more advanced usage of the library and continue our SimpleGame to be an actual game, a simple game that is. Stay tuned!