In my previous post (Introduction to Löve), I showed you how to start using the Löve framework to produce a game. While what we made wasn’t really a game exactly, it did have some of the foundational things you would need. In this post, we’re going to add a bit more. Specifically, we’re going to give the player more freedom of motion and add a second player.
First, let’s do a quick review of the code we should have from before.
function love.load() player = {} player.y = love.window.getHeight()/2 player.x = love.window.getWidth()/2 end
function love.update(dt) if love.keyboard.isDown('down') then player.y = player.y + 100*dt elseif love.keyboard.isdown('up') then player.y = player.y - 100*dt end end
function love.draw() love.graphics.circle('fill', player.x, player.y, 30) end
That code initializes a player table, stores some coordinates inside of it, and lets us use the up and down arrows on the keyboard to move the player up or down at a rate of 100 pixels per second. It then goes on to draw the player as a circle. So let’s dive right in.
The first thing we need to do is let people distinguish the player. We’ll do this by storing a color in the player entity. There are more elegant ways of doing this, but we’ll simply make another player, and give the player a color entry.
function love.load() playerOne = {} playerOne.y = love.window.getHeight()/2 - 20 playerOne.x = love.window.getWidth()/2 playerOne.color = {255,0,0,255} playerTwo = {} playerTwo.y = love.window.getHeight()/2 + 20 playerTwo.x = love.window.getWidth()/2 playerTwo.color = {0,255,0,255} end
Nothing really new there except a bit of additional Lua syntax. We’re storing each player’s color as a table inside of the “color” entry in their own table. Tables in a table, it happens all the time, and it’s very useful. Colors in Löve are defined as RGBA (Red, Green, Blue, Alpha). We’ll be using that color variable a bit later, but for now, let’s improve our player movement.
function love.update(dt) if love.keyboard.isDown('down') then playerOne.y = playerOne.y + 100*dt elseif love.keyboard.isdown('up') then playerOne.y = playerOne.y - 100*dt end if love.keyboard.isDown('left') then playerOne.x = playerOne.x - 100*dt elseif love.keyboard.isDown('right') then playerOne.x = playerOne.x + 100*dt end end
We didn’t do anything new. really. We’re using the same functions that we used previously, but this time we’re checking for some different keys. One thing worth pointing out is that we’re using if and elseif statements. It’s important to think about the order that things happen in the game. In our example, the code fire checks if the down key is pressed. If it is, then we aren’t even checking if the up key is pressed. This means that if both up and down are pressed, the player would move down. Same thing for left and right. If both left and right are pressed, then the player would move to the left. If we had merged everything into the same if and elseif statements, then we would only be able to accept one key at a time. As it stands, we are able to process up to two keys being concurrently pressed. If we were to break everything into their own if statements, then we could handle all keys being pressed at once.
Our next step is to make sure that we can distinguish between our players. Color is a great way of doing this. If you remember, we earlier made the players have a color. Let’s use it in our draw function now.
function love.draw() love.graphics.setColor(unpack(playerOne.color)) love.graphics.circle('fill', playerOne.x, playerOne.y, 30) love.graphics.setColor(unpack(playerTwo.color)) love.graphics.circle('fill', playerTwo.x, playerTwo.y, 30) end
Here we are using the setColor function, which accepts four arguments (R,G,B,A). It will then use that as a modifier for each draw operation performed after it. We could pass four independent arguments into the function, but we can use a handy function that’s built into Lua called unpack. This takes our table in a table and returns them all independently. That means we now have a nice way of dealing with player color. As has been pointed out by a commenter, the function is also intelligent enough to accept the table directly. That means that we could simply pass in playerOne.color and it would deal with it appropriately. That would also be better performing too (though only marginally at best.)
If you run the code now, you can move our circle around and give them color. Using what you’ve learned thus far, you should be able to produce another player with different controls and have them both be controlled independent of each other. Try it out! If you hit any snags or have any questions, feel free to post a comment. We’re here to help! My next post will build on this knowledge by showing you how to do some basic collision management along with tracking even more information about the players. Until then, happy coding!