Reading documentation
You typically run into two types of documentation for software: guides and API documentation.
Guides would be information on getting started, tutorials, and books.
An API (application programming interface) is a portion of software that a programmer writes for his/her program to allow fellow programmers to interact with their application.
As for LÖVE's programming interface, most of your interactions with the framework are done through the love
global variable that the framework purposely exposes.
API documentation is the most fundamental form of software documentation because without it, you would not know what all the functions in the program do unless you were resourceful enough to go in and study all the source code and figure each function out on your own.
The documentation for LÖVE (bookmark this!) is written in a wiki style where each table and function has an article that describes how to use it.
From here you should see many modules listed.
Click on love.physics
.
Again, love.physics
is just a table with functions in it.
So within the article we see each of the functions stored in it including the functions love.physics.newBody
which we used to create our entities' bodies, love.physics.newPolygonShape
which we used to create their shapes, and love.physics.newFixture
which we used to create their fixtures.
We also see love.physics.newWorld
which created our world table.
Let's look at the first function's article.
Clicking on the article for love.physics.newBody
we get a synopsis showing how the function might be used, along with a description of its parameters and what the function returns.
Over the course of different versions of the framework, functions may be modified so in the case of this function you can see examples of how to use it differently in different versions of LÖVE.
Since the function lists that it returns a body, click the link to go over to the article on the body table's documentation.
There's a lot of functions here that set properties on the body and get properties from the body.
One of them is the body:setMass
function we used to give our entity weight.
We can see that it takes one parameter and that the parameter is meant to simulate how many kilograms of mass the body has.
We originally told it that our triangle in the last section weighed 32 kilograms, which if you think the object fell too fast or too slow then you may need to adjust your world's gravity to match your expectation.
Now let's go back to love.physics
for a moment and take a look at one of the other components we added to our previous code, the fixture.
We previously created a fixture table by calling triangle.fixture = love.physics.newFixture(triangle.body, triangle.shape)
.
However, we haven't seen any of these functions in the fixture table that could come in handy.
For instance, we could give our triangle bounciness by invoking fixture:setRestitution
.
Our triangle fixture is named triangle.fixture
though, not fixture
.
If 0 is no bounciness (default) and 1 is 100%, try modifying the game code and adding a restitution of 75%:
triangle.fixture:setRestitution(0.75)
Try running the game and see how that works.
If you set the restitution to 1
or higher then the triangle won't stop bouncing and will bounce itself right off the screen.
Callbacks
Let's backtrack now to the main article about the love table.
If you scroll down a little on the page, you'll see a section titled "Callbacks" that contains some functions we've become familiar with such as love.draw
and love.update
.
This is a list of all the functions in the game loop that we have and haven't talked about yet.
A "callback" is a function you create and give to an API (the love
table in this case) that will later get invoked as needed.
Creating functions with these names allow you to tap into specific portions of the game loop and trigger your own events.
Let's take a look at the love.keypressed
callback for instance.
In the synopsis you see that it has 3 parameters (the documentation mistakenly calls parameters "arguments").
We used the first parameter key
to see what key was pressed.
If you ever need to know what keys are available, you can click on the link provided next to the parameter name, KeyConstant
to see a well-defined list of all the available key strings passed in to this parameter.
The second parameter scancode
we didn't talk about, but it has a well-defined Scancode
article explaining what it is.
If you are not familiar with scancodes, take a minute to read it and perhaps you'll learn about a feature you may want to use in your game.
One more callback we'll look at while we're here is love.focus
.
Take a moment to stop here and read what it does and what parameters it takes before continuing.
Now it would be really cool if we were making a game and when the user switched to another application window, the game automatically paused for the user.
So first let's start by implementing a pause feature in our earlier game code:
local world = love.physics.newWorld(0, 9.81 * 128)
-- Triangle is the name of our first entity
local triangle = {}
triangle.body = love.physics.newBody(world, 200, 200, 'dynamic')
-- Give the triangle some weight
triangle.body.setMass(triangle.body, 32)
triangle.shape = love.physics.newPolygonShape(100, 100, 200, 100, 200, 200)
triangle.fixture = love.physics.newFixture(triangle.body, triangle.shape)
triangle.fixture:setRestitution(0.75)
-- Another entity
local bar = {}
bar.body = love.physics.newBody(world, 200, 450, 'static')
bar.shape = love.physics.newPolygonShape(0, 0, 0, 20, 400, 20, 400, 0)
bar.fixture = love.physics.newFixture(bar.body, bar.shape)
-- Boolean to keep track of whether our game is paused or not
local paused = false
local key_map = {
escape = function()
love.event.quit()
end,
space = function()
paused = not paused
end
}
love.draw = function()
love.graphics.polygon('line', triangle.body:getWorldPoints(triangle.shape:getPoints()))
love.graphics.polygon('line', bar.body:getWorldPoints(bar.shape:getPoints()))
end
love.keypressed = function(pressed_key)
-- Check in the key map if there is a function
-- that matches this pressed key's name
if key_map[pressed_key] then
key_map[pressed_key]()
end
end
love.update = function(dt)
if not paused then
world:update(dt)
end
end
Notice the 3 changes:
- We added a boolean called
paused
and set it to false - We added a new function to
key_map
so that when"space"
is pressed, the value ofpaused
is set tonot paused
.not
is an operator for booleans we previously didn't discuss. It simply says "the opposite of this boolean". So ifpaused
istrue
, then settingpaused
tonot paused
will set it tofalse
. - Lastly, inside
love.update
to told the world to update only if we arenot paused
. So the passage of time in the game world will cease when pressing the space key.
Exercises
- Now with the documentation in hand, define
love.focus
and make it so the game pauses when the user clicks away from the game window. - Bonus: make the game print a text saying that the game is paused when
paused
istrue
. Go find the documentation forlove.graphics.print
to see an example on displaying text.