Using Sprite Sheets in Castle
Hello Castle community! I gave a live stream covering this tutorial. I’ll also be available in Discord if you need any help. You can also ping me on Twitter if you just want to ask me random things, I’m always available to help.
We’re doing a whole set of tutorial streams as part of Castle Halloween Party. See the full stream schedule here.
This is a tutorial for beginners! I will be covering the basics of using a sprite sheet in Castle. When we’re done your entire screen will be filled with explosions. The full source code is available here, along with other random experiments.
A sprite sheet is an image that consists of many smaller images. When you are performing an animation you could use individual image files, but combining the small images in one big image improves the game performance, reduces the memory usage and speeds up the startup time of the game.
There are many sprite sheets on the internet, you may have a couple saved to your computer. I’m going to show you how to use one on Castle.
Explosions.png
Here is the sprite sheet we’re going to work with! Right click and save it to your computer.
Source: https://opengameart.org/content/explosion-effects-and-more check the link out for more sprite sheets later!
Next, let’s create a directory on your computer called sprite-sheet-example
Once you’ve created a directory, use the touch command to create a file called main.lua
All we have to do now is move explosions.png over to this directory.
Time To Code
It is time to open main.lua in your favorite code editor. I use Sublime Text 3 but you can use something popular like VS Code, it makes no difference. Copy and paste this code snippet into main.lua:
function love.load()
--
endfunction love.update(dt)
--
endfunction love.draw()
--
end
It should look something like this:
Now open up Castle and open the project by clicking Create and selecting the open project / open another project option in the dropdown menu.
After clicking create, pick the main.lua file in your sprite-sheet-example folder.
Once you click Open Project you should see this on your screen:
For the sake of speed, I’m just going to have you copy and paste these snippets into main.lua.
Here is the first:
function newAnimation(image, width, height)
-- Lua as a programming language supports local variables.
-- Unlike global variables, local variables have
-- their scope limited to the block they are declared.
-- In this case, `newAnimation` is considered a `block`.
-- Canonically, a block is the body of a control
-- structure, in this case a function.
local animation = {} -- A table in Lua is an object in more than one sense.
-- We can store state in this object.
animation.spriteSheet = image;
animation.quads = {}; local y = 0
local x = 0
-- We can use the dimensions of the image we're providing.
-- explosions.png is a 512x512 image.
-- Since there are 4 rows and 4 columns,
-- each quadrant is 128px width, and 128px height.
-- Below is the syntax for a for loop.
-- We use the for loop to insert each part of the
-- sprite sheet into a Lua table.
for y = 0, image:getHeight() - height, height do
for x = 0, image:getWidth() - width, width do
-- The purpose of a Quad is to use a fraction
-- of an image to draw objects, as opposed to
-- drawing entire image.
table.insert(animation.quads, love.graphics.newQuad(x, y, width, height, image:getDimensions()))
end
end
-- These are some values that represent how long
-- we should spend in each frame of the sprite sheet animation.
animation.duration = 1
animation.current = 0
return animation
end
I call this type of function a utility function. It makes it easier to create animations.
Here is the next section, this is where we will initialize our explosion entities.
-- This local variable helps us keep track of all
-- of the entities we want to animate.
-- It can be used in other blocks.
local mounted = {}-- This function is called exactly once at
-- the beginning of the game.
function love.load()
-- You can use any values you like here.
-- I am going to initialize 20 explosions
-- by inserting 20 local variables
-- into a table.
for i = 0, 20, 1
do
local explosion = newAnimation(
love.graphics.newImage("explosion.png"),
128,
128
)
table.insert(mounted, explosion)
end
end
Since love.load() is only called once, it is the perfect place to keep references to all of our explosions.
After that, lets add love.update()
-- Callback function used to update the
-- state of the game every frame.
function love.update(dt)
-- Iterate over each of the explosions in the table.
for i, v in pairs(mounted) do
-- For each explosion,
-- update the animation duration of the frame.
mounted[i].current = mounted[i].current + dt -- If the current duration is greater than the max duration
-- Reset the duration.
if mounted[i].current >= mounted[i].duration then
mounted[i].current = 0
end
end
end
Finally, let us add the love.draw() function:
-- Callback function used to draw on the screen every frame.
function love.draw()
-- Iterate over each of the explosions in the table.
for i, v in pairs(mounted) do
-- This is just to make it easier to reference the explosion.
local currentExplosion = mounted[i] -- Which sprite we are going to animate.
local spriteNum = math.floor(
currentExplosion.current / currentExplosion.duration * #currentExplosion.quads
) + 1 -- Get the dimensions of your current screen.
local width, height = love.graphics.getDimensions() -- Draw one of the explosions.
love.graphics.draw(
currentExplosion.spriteSheet,
currentExplosion.quads[spriteNum],
math.random(0, width),
math.random(0, height)
)
end
end
love.graphics.draw() is a function that makes the magic happen, let us have a look at what we are passing in.
The first argument is a reference to our image file, explosions.png.
The second argument is the current quadrant of that image file to draw. Remember when we saved that state (love.graphics.newQuad) in our table in the function newAnimation?
The third argument is the x position on the screen to draw the image.
The fourth argument is the y position on the screen to draw the image.
Time For Some Explosions
Once you have all of the snippets above in your main.lua file. Hit command+R to refresh the screen, and you should see the following:
And it is a simple as that! Now you have an example of how to use sprite sheets in Castle.
Feel free to ask me on Twitter if you have any other questions, I’m always down to help! Thanks for taking the time to check out Castle.