UFO Game
We'll be creating a little demo that sees a UFO move around the screen using
the keyboard. Create a new folder, then add the following code to a new
main.lua
file:
function spry.conf(t)
t.window_title = 'UFO Demo'
end
kenney.nl provides free
(public domain) game assets. One of the asset packs includes
a green UFO. Add it to the game folder, and load it
using spry.image_load
.
function spry.start()
ufo = spry.image_load 'green-ufo.png'
end
Player Class
We'll create a new file called player.lua
with the following contents:
class 'Player'
function Player:new()
self.x = spry.window_width() / 2
self.y = spry.window_height() / 2
end
function Player:draw()
ufo:draw(self.x, self.y)
end
Inside spry.start
, We'll create a new player back in the main.lua
file:
function spry.start()
ufo = spry.image_load 'green-ufo.png'
player = Player()
end
Player()
calls the Player:new
method. The player's x and y position is
one half of the window's width and height. In other words, we're setting the
player's position to the center of the screen.
Player:draw
uses the ufo image that we load during program startup in
spry.start
. The image is drawn with the player's x and y position.
Let's create spry.frame
in main.lua
. In this function, we'll draw the
player:
function spry.frame(dt)
player:draw()
end
You do not need to include the newly created file inside main.lua
. All Lua
scripts in your project folder are loaded on startup. Once you run your game,
you should see a ufo on the screen:
spry.exe my_folder
Keyboard Input
We'll use keyboard input to move the player. Create a new Player:update
method:
function Player:update(dt)
local vx, vy = 0, 0
if spry.key_down 'w' then vy = vy - 1 end
if spry.key_down 's' then vy = vy + 1 end
if spry.key_down 'a' then vx = vx - 1 end
if spry.key_down 'd' then vx = vx + 1 end
end
vx
and vy
stands for velocity x, and velocity y. These variables represent
the player's horizonal and vertical speed. When the user presses any of the
WASD keys, the velocity changes appropriately. In the case of the D key, vx
is set to itself, plus 1, representing movement towards the right side of the
screen.
Now we'll move the player by setting the x and y position. Put the following
code inside Player:update
, just before the function ends:
local move_speed = 200
self.x = self.x + vx * move_speed * dt
self.y = self.y + vy * move_speed * dt
Whenever we move something, we need to make sure the movement is framerate
independent. This is done by multiplying movement speed by delta time dt
(the time spend between this frame and last frame). We'll pass dt
to the
player's update method through spry.update
:
function spry.frame(dt)
player:update(dt)
player:draw()
end
Run the game again and try moving the UFO using the WASD keys.
Image Origin
When drawing the UFO, the image origin starts at the top-left. If you want the
player to be exactly centered, change Player:draw
:
function Player:draw()
local rotation = 0
-- scale
local sx = 1
local sy = 1
-- image origin
local ox = ufo:width() / 2
local oy = ufo:height() / 2
ufo:draw(self.x, self.y, rotation, sx, sy, ox, oy)
end
Here, we're adding additional info to ufo:draw
. To set the image origin to
the center of the image, get the image dimensions with ufo:width
and
ufo:height
, and divide by 2. In order to set the image origin, we also need
to explicitly set the image's rotation, horizontal scale, and vertical scale
first.
Movement Fix
You might notice that moving diagonally is a little faster compared to
vertical or horizonal movement. This is because vertical and horizontal
movement has a speed of 200, but using both vertical and horizontal speeds
together results in a speed of around 282 (square root of 2002 +
2002). We need to normalize vx
and vy
so that the combined
speed of both vx
and vy
is always 1.
After setting keyboard input, but before moving the player, add the following line:
vx, vy = normalize(vx, vy)
Run the game again, and you'll see that the player moves at the same speed regardless of direction.