Introduction: A Simple Animation in LÖVE (lua)
Today we're gonna take a look at how to make a simple animation in LÖVE without the use of libraries.
We'll also take a look at what exactly LÖVE is and how you can create your own games.
Step 1: What Is LÖVE?
LÖVE is a free open source framework which uses lua to make 2d games. It works on Windows, Mac OS X, Linux, Android and iOS.
Why use LÖVE?
- LÖVE is open source
- LÖVE can be used freely for commercial purposes without limitations
- The community, there's a lot of helpful people which likely will help you out once you get stuck
- Very easy to learn, it uses both lua and LÖVE syntax
love.graphics.print("Hello World!", 400, 300)
Drawing an image:
whale = love.graphics.newImage("whale.png")
love.graphics.draw(whale, 300, 200)
Discord server: https://discord.gg/rhUets9
IRC chat: https://webchat.oftc.net/?channels=love
Step 2: Getting Started
So first of all open any kind of text editor to write your file, see how it's structured below.
The structure of a LÖVE program always looks like this (as seen in the picture):
function love.load() -- in this function you usually want to declare all your variables
function love.update() -- this is the main game loop, use this for changing variables at certain conditions.
function love.draw() -- this is also a loop like love.update, the only difference is this function can draw images etc
in lua "--" is used to comment a line.
Step 3: Declaring Our Variables
before we can even think of making our animation we have to declare some variables.
Which include the amount of frames per second should be displayed and how many frames there are.
without these we're unable to do anything! the variables we will add are as follows:
local fps = 7
local frame = 1
local animation_duration = 1 / fps
local frame_number = 4
now, i've said what variables we need but what exactly do they mean? well let's dive a bit deeper on that!
local fps -- this is how many frames per second the animation will display
local frame -- the animation's starting frame, obviously we will start at the 1st frame so it will be 1
local animation_duration -- this one handles how long the frame should be displayed to achieve the right fps
local frame_number -- this one here just says how many frames our animation has, in this case 4.
local xupdate -- xupdate will handle the starting reading point of the quad for the animation
Step 4: Love.load() Function
Here's the code we're gonna use in love.load, love.load gets loaded only once on startup of the program after that it's never run again so if you want to update variables you should do so in love.update.
walkinganim = love.graphics.newImage("anim.png")
walk = love.graphics.newQuad(0, 0, 120, 120, walkinganim:getDimensions()) **
**depends on which image you're using if you're using the 120 x 120 leave it as shown else make it 12 x 12
Breaking down the code:
love.graphics.setDefaultfilter("nearest") -- sets the default scaling image filter.
walkinganim = love.graphics.newImage("anim.png") -- storest the anim.png image in the walkinganim variable
walk = love.graphics.newQuad(0, 0, 120, 120, walkinganim:getDimensions()) -- this one is made up off of multiple pieces of code so let's break it down first of all, "What is a quad?" A quadrilateral (a polygon with four sides and four corners) with texture coordinate information. so in short it breaks our sprite sheet down into a single image which we stored in the variable walk.
inside the parenthesis we want to put certain coordinates(startx, starty, imagewidth, imageheight, imagedimensions)
at startx and starty you want to place the starting coordinates of your sprite sheet, most likely 0, 0.
imagewidth and imageheight are the width and height of the single frame you want to diplay in our case either 12 x 12 or 120 x 120 depending on which image you're using.
now after that there's: walkinganim:getDimensions() the variable we made "walk" needs a reference image our sprite sheet how else is it gonna know which image to take the part from.
Step 5: Love.update(dt) Function
Here we'll discuss the love.update(dt) function which is our main loop for changing variables, if you don't like to read this one's gonna be pretty boring.
so let's put our code here (pic above):
if dt < 0.04 then
animation_duration = animation_duration - dt
if animation_duration <= 0 then
animation_duration = 1 / fps
frame = frame + 1
if frame > frame_number then
frame = 1
xupdate = 12 * (frame - 1)
Now let's break down our code!
starting off with dt, what does dt mean? dt stands for delta-time which is the amount of time which has passed since the last time love.update has been called
if dt < 0.04 then -- this little guy right here makes sure that dt (delta - time) is not bigger than 0.04 seconds if it is the animation won't work, if the animation just freezes and does nothing, increase this number; you might ask why do we use it then? the answer is pretty simple if you don't use it, it can cause frame skips upon moving the executable window.
animation_duration = animation_duration - dt -- this makes sure that the animation will always have the same speed no matter how fast the computer is
if animation_duration <= 0 then -- the if statement will only work if animation_duration is below 0 well to do the maths; (animation_duration started at 1 / 7 (1 / fps) if we do that we get 0.14, if you substract delta time from it it will always be below or equal to 0). just a hard way to say it should always loop.
animation_duration = 1 / fps --we have to reset our animation_duration every loop to keep the display rate right.
frame = frame + 1 -- we want the next frame to be played every time it loops so we increase our frame with 1.
if frame > frame_number then -- we do not want our current frame to exceed our max amount of frames because this could result in a crash or just an empty image. so when we reach frame 5, which does not exist we set frame back to 1. this also makes it an infinitely looping frame.
frame = 1
xupdate = 12 * (frame - 1) -- this command will change our starting x position on the image by moving this we can choose different frames along the x axis, the 12 is dependent on the single sprite size.
else return -- basically if the dt is greater than 0.04 do nothing end
Step 6: Love.draw() Function
in the love.draw function we only have to add our drawable, this is a single image.
love.graphics.draw(walkinganim, walk, 100, 200, 0, 10, 10)
let's break this last funtion down!
love.graphics.draw(image, quad, x, y, r, sx, sy)
image -- here's were we use our spritesheet as image reference.
quad -- the quad we made earlier, the one that stored the single image
x -- the position on the x axis
(orientation is from the left top corner of the image)
y -- the position on the y axis
r -- rotation of the image
sx -- scaling factor on the x axis 10 if you're using the 12 x 12, 0 if you're using the 120 x 120
sy -- scaling factor on the y axis 10 if you're using the 12 x 12, 0 if you're using the 120 x 120
After you're done save your file as main.lua this is a necessity as LOVE will use this file as main executable.
Step 7: How to Run Your Newly Made Program
A computer does not automatically have LOVE installed you can however download an IDE (Integrated Development Enviroment). The IDE also contains a text editor and syntax highlighting.
When using the IDE you still have to download LOVE seperately though.
on top of that it also gives you a crash report in the console if you were to make a fault.
When you're making use of the IDE (zerobrane studio) you want to change the project directory and the project interpreter. Now how you do this can be found in the images above.