# Show your Pi Some LÖVE
by Seth Kenlon

The Raspberry Pi is famous for introducing kids to open source
software and programming. It's an affordable, practical introduction
to professional-grade computing, disguised as hackable fun. The
application that's done the most to get young children started in
programming has been Mitch Resnick's Scratch (which was fortunately
[forked by the Pi Foundation](http://github.com/raspberrypi/scratch)
when Scratch 2 switched to the non-open Adobe Air), but an inevitable
question is what someone should graduate to after they've outgrown
drag-and-drop programming.

There are many candidates for the next level of programming after a
drag-and-drop intro like Scratch. There's the excellent
[PyGame](http://pygame.org), a Java subset called
[Processing](http://processing.org), the
[Godot](http://godotengine.org), and many others. The trick is to find
an engine that is easy enough to ease the transition from the instant
gratification of drag-and-drop, but complex enough that it
accurately represents what professional programmers actually do all
day.

A particularly robust game engine is called
[LÖVE](http://love2d.org). It uses the scripting language
[Lua](http://lua.org), which doesn't get as much attention as Python,
but is actually [heavily
embedded](https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Lua_Abilities_and_Modifiers)
(both literally and figuratively) in the modern video game
industry. It's listed as a skill by almost all the major game studios,
it's an option in the proprietary Unity and Unreal game engines, and
it generally pops up in all kinds of unexpected places in the real
world. To make a long story short, Lua is a language worth learning,
especially if you're planning on going into game development. As for
as the LÖVE engine is concerned, it's about as good as the PyGame
framework in terms of features, and since it has no IDE, it is very
lightweight and, in a way, less complex to learn than something like
Godot.

Better yet, LÖVE runs on the Pi natively, but its projects can be open
and run on any platform that Lua does. That includes Linux, Windows,
and Mac, but also Android and even the oh-so-closed iOS. In other
words, it's not a bad platform to get started in mobile development,
too.

![Mr. Rescue, an open source game available on itch.io](love_rescue.png)

Now that I've sold you on LÖVE as the next step up from Scratch on the
Pi, let's dig in and see how it works.

## Intalling LÖVE

As usual, installing LÖVE is just one easy command on the Raspberry Pi:

   $ sudo apt install love2d

If you're running [Fedora on your Pi](https://opensource.com/article/17/3/how-install-fedora-on-raspberry-pi), use `dnf` instead:

   $ sudo dnf install love2d

Either way, the package management system pulls in Lua, SDL, and other
dependencies that LÖVE needs to run.


## Hello World

There's not much to see in the LÖVE engine. It's really just a
framework, meaning you can use whatever text editor you prefer. First
thing to try is a "hello world" program, just to make sure it
launches, and to introduce you to the basic syntax of both the Lua
language and the LÖVE framework.

Open a text editor and enter this text:

   cwide = 520
   chigh = 333

   love.window.setTitle(' Hello Wörld ')
   love.window.setMode(cwide, chigh)

   function love.load()
       love.graphics.setBackgroundColor(177, 106, 248)
       -- font = love.graphics.setNewFont("SkirtGirl.ttf", 72)
   end

   function love.draw()
       love.graphics.setColor(255, 33, 78)
       love.graphics.print("Hello World", cwide/4, chigh/3.33)
   end

Save that as `main.lua`.

A distributable LÖVE package is just a zip file, with the `.love` extension. The main file, which must always be named `main.lua`, must be at the top level of the zip file. Create it like this:

   $ zip hello.love main.lua

And launch it:

   $ love ./hello.love

![Hello World](love_hello.png)

The code is pretty easy to understand. The `cwide` and `chigh`
variables are global, available to the whole script, and they set the
width and height of the game world. In the first block of code (called
a `function`), the background color is set, and in the second function
the "hello world" gets printed to the screen.

The line preceded by two dashes (--) is a comment. Including a `.ttf`
in the `.love` package and uncommenting the `setNewFont` line renders
text in that font face.

   $ zip hello.love main.lua SkirtGirl.ttf

And launch it:

   $ love ./hello.love


## The Basics

One big difference between Scratch and a professional programming
language is that with Scratch, you can learn a few basic principles
and then just randomly explore until you've discovered all the other
features.

With lower-level programming languages like Lua, the things you learn
first aren't things you can just copy and paste to produce a playable
game. You learn how to use the language, and then you look up
functions that accomplish actions that you want your game to
feature. Until you learn how the language works, it's difficult to
blindly stumble your way into a working game world.

Luckily, you can learn the language as you build the start of a game.
Along the way, you pick up some tricks that you can reuse later to make
your game work the way you want it to work.

To begin with, you need to know the three main functions in the core
LÖVE engine:

**function love.load()** is the function that gets triggered when you
launch a LÖVE game (it's called the "init" or "void setup()" function
in other languages). It's used to set up the groundwork for your game
world. It only gets executed once, so the only thing it contains is
code that persists throughout your game. It's, more or less, the
equivalent of the **When Green Flag is Clicked** block and the
**Stage** script area in Scratch.

**function love.update(dt)** is the function that gets constantly
updated during game play. Anything in a love.update(dt) function is
refreshed as the game is played. If you've played any game, whether
it's Five Nights at Freddy's or Skyrim or anything else, and you've
monitored your framerate (fps), everything happening as the frames
tick would be in an update loop (not literally, since those games
weren't in LÖVE, but something like an update function).

**function love.draw()** is a function that causes the engine to
instantiate the graphical components that you created in the
**love.load()** function of your game. You can load a sprite or create
a mountain, but if you don't draw it then it never shows up in your
game.

Those are the three functions that serve as the foundation for any
element you create in LÖVE. You can create new functions of your own,
too. First, let's explore the LÖVE framework.


## Sprites

The basics of the "Hello, World" is a good starting point. The same
basic three functions still serve as the basic skeleton of the
application. Unlike rendering simple text on the screen, though, this
time we create a sprite using a graphic from
[openclipart.org](https://openclipart.org).

The code examples and assets for this example are available in a [git
repository](https://notabug.org/seth/lessons_love2d). Clone it for
yourself if you want to follow along:

   git clone https://notabug.org/seth/lessons_love2d.git

Most objects in LÖVE are stored in arrays. An array is a little like a
list in Scratch; it's a bunch of characteristics placed into a common
container. Generally, when you create a sprite in LÖVE, you create an
array to hold attributes about the sprite, and then list the
attributes in `love.load` that you want the object to have.

In the `love.draw` function, the sprite gets drawn to the screen.

   fish  = {}
   cwide = 520
   chigh = 333

   love.window.setMode(cwide, chigh)
   love.window.setTitle(' Collide ')

   function love.load()
       fish.x    = 0
       fish.y    = 0
       fish.img  = love.graphics.newImage('images/fish.png')
   end

   function love.update(dt)
       -- this is a comment
   end

   function love.draw()
       love.graphics.draw(fish.img, fish.x, fish.y, 0, 1, 1, 0, 0)

   end

The fish's natural predator is one of the most vicious creatures of
the antarctic: the penguin. Create a penguin sprite in the same way as
the fish sprite was created, with the addition of a `player.speed`,
which is how many pixels the penguin will move once we get around to
setting up player controls.

   fish  = {}
   player= {}
   cwide = 520
   chigh = 333

   love.window.setMode(cwide, chigh)
   love.window.setTitle(' Collide ')

   function love.load()
       fish.x    = 0
       fish.y    = 0
       fish.img  = love.graphics.newImage('images/fish.png')
       player.x     = 100
       player.y     = 100
       player.img   = love.graphics.newImage('images/tux.png')
       player.speed = 10
   end

   function love.update(dt)
       -- this is a comment
   end

   function love.draw()
       love.graphics.draw(fish.img,  fish.x,  fish.y,  0,1,1,0, 0)
       love.graphics.draw(player.img,player.x,player.y,0,1,1,0, 0)
   end

To keep things tidy, place the `png` files in an `images`
directory. To test the game as it is so far, zip up the `main.lua` and
`png` files.

   $ zip game.zip main.lua -r images
   $ mv game.zip game.love
   $ love ./game.love

![Our current cast of characters.](love_sprites.png)

## Movement

There are several ways to implement movement in LÖVE, including
functions for mouse, joystick, and keyboard. We've already established
variables for the player's `x` and `y` positions, and for how many
pixels the player moves, so use an if/then statement to detect key presses, and then redefine the variable holding the position of the player sprite using simple maths:

   player     = {}
   fish       = {}
   cwide      = 520
   chigh      = 333

   love.window.setMode(cwide, chigh)
   love.window.setTitle(' Collide ')

   function love.load()
       fish.x    = 0
       fish.y    = 0
       fish.img  = love.graphics.newImage( 'images/fish.png' )
       player.x     = 100
       player.y     = 100
       player.img   = love.graphics.newImage('images/tux.png')
       player.speed = 10
   end

   function love.update(dt)
       if love.keyboard.isDown("right") then
           player.x = player.x+player.speed

       elseif love.keyboard.isDown("left") then
           player.x = player.x-player.speed

       elseif love.keyboard.isDown("up")  then
           player.y = player.y-player.speed

       elseif love.keyboard.isDown("down") then
           player.y = player.y+player.speed
       end
   end

   function love.draw()
       love.graphics.draw(player.img,player.x,player.y,0,1,1,0, 0)
       love.graphics.draw(fish.img, fish.x, fish.y, 0, 1, 1, 0, 0)
   end

Test the code to confirm that movement works as expected. Remember to
re-zip all the files before testing so that you don't accidentally
test the old version of the game.

To make the movement make a little more sense, we can create functions
to change the direction a sprite is facing depending on what key is
pressed.

This is the equivalent of these kinds of Scratch code blocks:

![Looking and moving in Scratch](scratch-right.png)

Generate a flipped version of the player sprite using Image Magick:

   $ convert tux.png -flop tuxleft.png

And then write a function to swap out the image. You need two functions: one to swap out the image, and another to restore it to the original:

   function rotate_left()
       player.img = love.graphics.newImage('images/tuxleft.png')
   end

   function rotate_right()
       player.img = love.graphics.newImage('images/tux.png' )
   end

Use these functions where appropriate:

   function love.update(dt)
       if love.keyboard.isDown("right") then
           player.x = player.x+player.speed
           rotate_right()

       elseif love.keyboard.isDown("left") then
           player.x = player.x-player.speed
           rotate_left()

       elseif love.keyboard.isDown("up")  then
           player.y = player.y-player.speed

       elseif love.keyboard.isDown("down") then
           player.y = player.y+player.speed
       end
   end


## Automated movement

Using the same convention of the sprite's `x` value, and a little
mathematics, you can make the fish automatically move across the
screen from edge to edge.

This is the equivalent of doing this in  Scratch:

![Automated movement in Scratch](scratch-edge.png)

There is no `if on edge, bounce` in LÓVE, but by checking whether the
fish's `x` value has reached the far left of the screen, which is `0`
pixels, or the far right, which is the same as the width of the canvas
(the `cwide` variable), you can determine whether the sprite has gone
off the edge or not.

If the fish is at the far left, then it has reached the edge of the
screen, so you increment the fish's position forcing it to move
right. If the fish is at the far right, then decrement the fish's
position, making it move left.

   function automove(obj,x,y,ox,oy)
       if obj.x == cwide then
           local edgeright = 0
       elseif obj.x == 0 then
           local edgeright = 1
       end

       if edgeright == 1 then
           obj.x = obj.x + x
       else
           obj.x = obj.x - x
       end
   end

There's a sequence of events that happens to be important in this
case. In the first `if` block, you check for the value of `x` and
assign a temporary (local) variable to indicate where the fish needs
to go next. Then in a second, separate `if` block, you move the
fish. For bonus points, try doing it all in one `if` statement and see
if you can understand why it fails. For more bonus points, see if you
can figure out a different way of moving the fish.

To implement the fish's movement function, call the function at the
bottom of the `love.update` loop:

   automove(fish,1,0,fish.img:getWidth(),fish.img:getHeight() )

If you test the script, you'll notice that the fish goes all the way
off the screen when it hits the right edge. It's doing this because a
sprite's `x` value is based on its upper left pixel. I'll leave it as
an exercise for you to figure out what variable you should subtract
from `cwide` when checking for the fish's position.

## Collision detection

Video games are all about collisions. It's when things bump into each
other, whether those things are an unfortunate hero taking a dive into
a lava pit, or a bad guy getting blasted with a mana bolt, stuff is
supposed to happen.

Before detecting a collision, let's decide what we want to have happen
when a collision happens. Since you already know how to change a
sprite's appearance, we'll create two functions: one to change the
fish to just the bones left over after the penguin has caught it, and
the other to change the fish back to life any time the penguin isn't
around.

   function falive()
       fish.img = love.graphics.newImage('images/fish.png')
   end

   function fdead()
       fish.img = love.graphics.newImage('images/fishbones.png')
   end

With these functions set up, it's time to calculate collisions.

In Scratch, there are code blocks to check whether two sprites are
touching.

![Scratch collision](scratch-collision.png)

The same concept, in principle, applies in LÖVE. There are
several different ways to detect collisions, including external
libraries like [HC](https://github.com/vrld/HC) and `love.physics`,
but a good compromise between the two is a custom function to detect
an overlap in sprite boundaries.

   function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
       return x1 < x2+w2 and
           x2 < x1+w1 and
           y1 < y2+h2 and
           y2 < y1+h1
   end

The math is complex, but it makes sense if you take a moment to think
about it. The goal is detect whether two images are overlapping. If
the images are overlapping, they can be said to have collided. Here's
an illustration of two boxes *not* overlapping, with just some sample
`y` values to keep things simple:

![Two boxes](overlap_no.png)

Take a line from the function and crunch the numbers:

   y2  < y1 + h1
   110 < 0  + 100

That's obviously a false statement, so the function must return `false`. In other words, the boxes have not collided.

Now look at the same logic with two overlapping boxes:

![Overlapping boxes](overlap.png)

   y2  < y1 + h1
   50  < 0  + 100

This one is clearly true. Assuming all statements in the function are
also true (and they would be, had I bothered adding `x` values), then
the function returns `true`.

To leverage the collision check, just evaluate it with an `if`
statement. You know now that if the `CheckCollision` function returns
`true`, then there is a collision. The `CheckCollision` function has
been written very generically, so when calling it, you need to feed it
the appropriate values so it knows which object is which.

Most of the values are intuitive. You need LÖVE to use the `x` and `y`
positions of each object being checked for collision, and the size of
the object. The only values that are special in this case is the one
that gets swapped out depending on the collision state. For those,
hard code the size of the dead fish rather than the live fish, or else
the state of the collision will get changed in the middle of the
collision detection. In fact, if you want to see it glitch, you can do
it the wrong way first:

   if CheckCollision(fish.x,fish.y,fish.img:getWidth(),fish.img:getHeight(), player.x,player.y,player.img:getWidth(),player.img:getHeight() ) then
       fdead()
   else
       falive()
   end

The right way is to get the size of the smaller sprite image. You can do this with Image Magick:

   $ identify images/fishbones.png
   images/fishbones.png PNG 150x61 [...]

Then hard coded the "hot spot" with the appropriate dimensions:

   if CheckCollision(fish.x,fish.y,150,61, player.x,player.y,player.img:getWidth(),player.img:getHeight() ) then
       fdead()
   else
       falive()
   end

The side effect of hard coding the collision detection area is that
when the penguin touches just the edge of the fish, the fish doesn't
get gobbled up. For more precise collision detection, explore the
[HC](https://github.com/vrld/HC) library or `love.physics`.

## Final code

It's not much of a game, but it demonstrates the important elements of
video games:

   player     = {}
   fish       = {}
   cwide      = 520
   chigh      = 333

   love.window.setTitle(' Hello Game Wörld ')
   love.window.setMode(cwide, chigh)

   function love.load()
       fish.x    = 0
       fish.y    = 0
       fish.img  = love.graphics.newImage( 'images/fish.png' )
       player.x     = 150
       player.y     = 150
       player.img   = love.graphics.newImage('images/tux.png')
       player.speed = 10
   end

   function love.update(dt)
       if love.keyboard.isDown("right") then
           player.x = player.x+player.speed

       elseif love.keyboard.isDown("left") then
           player.x = player.x-player.speed

       elseif love.keyboard.isDown("up")  then
           player.y = player.y-player.speed

       elseif love.keyboard.isDown("down") then
           player.y = player.y+player.speed
       end

       if CheckCollision(fish.x,fish.y,151,61, player.x,player.y,player.img:getWidth(),player.img:getHeight() ) then
           fdead()
       else
           falive()
       end

       automove(fish,1,0,fish.wide,fish.high)
   end

   function love.draw()
       love.graphics.draw(player.img,player.x,player.y,0,1,1,0, 0)
       love.graphics.draw(fish.img, fish.x, fish.y, 0, 1, 1, 0, 0)
   end

   function automove(obj,x,y,ox,oy)
       if obj.x == cwide-fish.img:getWidth() then
           edgeright = 0
           elseif obj.x == 0 then
           edgeright = 1
       end

       if edgeright == 1 then
           obj.x = obj.x + x
       else
           obj.x = obj.x - x
       end
   end

   function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
       return x1 < x2+w2 and
           x2 < x1+w1 and
           y1 < y2+h2 and
           y2 < y1+h1
       end

   function rotate_left()
       player.img = love.graphics.newImage('images/tuxleft.png')
   end

   function rotate_right()
       player.img = love.graphics.newImage('images/tux.png' )
   end

   function falive()
       fish.img = love.graphics.newImage('images/fish.png')
   end

   function fdead()
       fish.img = love.graphics.newImage('images/fishbones.png')
   end

From here you can use the principles you've learned to
create more exciting work. Collisions are the basis for most
interactions in video games, whether it's to trigger a conversation
with an NPC, manage combat, pick up items, set off traps, or most
anything else, so if you master that, the rest is repetition and elbow
grease.

So go and make a video game! Share it with friends, play it on mobile,
and, as always, keep leveling up.