GameDev with Love (2D)

by Renato Sanchez

Tue Jul 23 2024

games

Start your Love2d journey!!! I'll get over libreries and programming technices to get a finel game.

Love2d is a great framework for getting into game development because many engines work with quite complex concepts behind the scenes. For this reason, I started using Love2d for personal basic projects, and I’m here to explain how to get started in this way.

Installing Love2d

To run Love2d, you first need to install Lua, which is a powerful programming language used in many modern projects like Neovim, web apps, and Roblox map-making.

On Windows (Chocolatey):

choco install lua53

On Ubuntu:

sudo apt install lua5.3 # or other versions

On other systems:

#------- Brew -------
brew install lua

#------- Arch-based (pacman) -------
sudo pacman -S lua

#------- On RHEL, CentOS, Rocky, and AlmaLinux -------
yum install epel-release
yum install lua

#------- On Fedora Linux -------
dnf install lua

Once you have installed Lua, Love2d will be available. I recommend visiting the official website and following the instructions depending on your system.

Game Structure

Love2d works with 3 basic functions: load(), update(), draw(). Each of these functions must be declared in the main file named main.lua, which is essential for running Love2d (where all the physics, classes, objects, and other game elements are handled).

main.lua

Here, we are going to write our first Love2d game! So let’s get started. First, we need to put the functions into the main.lua file.

function love.load() end
function love.update(dt) end
function love.draw() end

Now, let’s discuss them.

love.load()

Inside this function, we are going to load all the necessary resources for the game; we can also create bodies, load images, set timers, define variables, etc. This is because some things don’t need to be loaded every frame, and here we can call them for later use.

love.update(dt)

Here, the game is updated every frame. This includes calculating math, angles, algorithms, and everything needed to draw the game. In this function, we’ll bind all the keys to wait for input and trigger actions.

love.draw()

Every character needs a sprite or a figure (at minimum), and inside this function, we declare this using love.graphics functions, giving us access to all the geometric functions to draw and paint sprites.

Libraries

In this course, we can use the built-in functions of Love2d, but I think it’s unnecessary since many people on the internet have created a whole set of libraries ready to use. That’s why I’ve decided to present the libraries I use in my projects. I’m grateful to a327ex for creating a Love2d blog where I learned a lot, and for making many libraries for Love2d.

I highly recommend checking out the documentation for each library. You can also check out this repo where there are more libraries for Love2d.

awesome-love2d

A curated list of amazingly awesome LÖVE libraries, resources and shiny things.

null
3256 209

Object-Oriented Programming

classic

Tiny class module for Lua

Lua
853 93

When we are developing a game is necesary to generate objects to control each character, npc or item in the game. Love2d doesn’t includes an OOP handler or manager, that’s why I like to use Classic, because this librarie manage tipical functions of Objects like extend() or self.super:func() to call functions of parent objects.

I like to create one file for each character. For example, on a Player.lua:

Object = require("path/to/Object")
Player = Object:extend()

function Player:new(area,x,y,opts)
  self.super:new(area,x,y,opts)
end

function Player:update(dt)
  self.super:update(dt)
  --update body physics

  --update controls
end

function Player:draw()
  self.super:draw()
end

On this way we call the object Player on the main.lua by :



Physics

windfield

Physics module for LÖVE

Lua
452 55

This library is pretty easy to use because it sets up all the necessary components to handle a body. I like this because we don’t want problems while coding the game.

Windfield works like this: first, you create a world, then you can create bodies, joints, and apply physics.

Here’s an example:

Physics = require("path/to/windfield")

function love.load()
  -- create a world with no gravity
  world = Physics.newWorld(0,0)

  -- create a rectangle at (0,0) with dimensions 10x30
  body = world:newRectangleCollider(0,0,10,30)
  -- we can modify every attribute of the body
  body:setRestitution(0.1)
end

function love.update(dt)
  -- update the world physics
  world:update(dt)
end

function love.draw()
  -- draw the world (only body borders)
  world:draw()
end

Inputs

boipushy

Input module for LÖVE

Lua
149 25

Every game needs an input flux to work, and this librarie will help us to manage that input signs.

function love.load()
  IN = Input()
  IN:bind("up","jump")
  IN:bind("left","move_left")
  IN:bind("right","move_right")
end

function love.update(dt)
  if IN:pressed"jump") then
    --calculate the jump - pressed only evaluate when the key goes down.
  end
  if IN:down("move_left") then
    --calculate move to left - down evaluate every cycle while the key is down.
  end
end

Camera

STALKER-X

Camera module for LÖVE

Lua
268 21

The camera is pretty important to get a inmersive game, that’s why I love to use this lib, because is simple and ready to use.

function love.load()
  camera = Camera()
end

function love.update(dt)
  camera:update(dt)
end

function love.draw()
  camera:attach()
  -- Draw your game here
  camera:detach()
  camera:draw() -- Call this here if you're using camera:fade, camera:flash or debug drawing the deadzone
end

Timers

hump

LÖVE Helper Utilities for Massive Progression

Lua
1082 153

When and enemy or item is alive, the most of the time they internally have a timer with a predefined or random lifetime (miliseconds ,seconds or minutes).

function love.keypressed(key)
  if key == ' ' then
    Timer.after(1, function() print("Hello, world!") end)
  end
end

function love.update(dt)
  Timer.update(dt)
end

UI

Buttons, input text or modals are essential to interact with the game interface, maybe on a main menu or settings menu.

local yui = require 'lib.yui'

function love.load()
  local w, h = 300, 80
  local x = math.floor((love.graphics.getWidth() - w) / 2)
  local y = math.floor((love.graphics.getHeight() - h) / 2)

  ui = yui.Ui:new {
    x = x, y = y,

    yui.Rows {
      yui.Label {
        w = w, h = h / 2,
        text = "Hello, World!"
      },
      yui.Button {
        text = "Close",

        onHit = function() love.event.quit() end
      }
    }
  }
end

function love.update(dt)
  ui:update(dt)
end

function love.draw()
  ui:draw()
end

https://gitea.it/1414codeforge/yui

Extras

Moses

Utility library for functional programming in Lua

Lua
628 104