Trying to load a sprite.
First of all, get some sprites. As I’m currently fixated with cats I bought from itch.io this set as a starting point https://seethingswarm.itch.io/catset. I don’t know why I am fixated with cats, I am the Philosophical Dog after all. But anyway.
Let’s choose some sprites. Running is good.
We need to convert them to 1 bit. I went with https://doodad.dev/dither-me-this/. The end result isn’t enormously pretty but it’s good enough to start with.
There’s a lot of research to be done in making this sort of thing better. But let’s see how we get on. The following code will load the cat_sheet image, make one sprite from it and display on the screen. It’s not moving, it doesn’t fit, there’s no animation.
import 'CoreLibs/graphics'
import 'CoreLibs/sprites'
local gfx <const> = playdate.graphics
local catSheet = gfx.image.new('images/cat_sheet')
local catSprite = gfx.sprite.new(catSheet)
print(catSheet, catSprite)
catSprite:moveTo(200, 120)
catSprite:add()
function playdate.update()
gfx.sprite.update()
end
Can we animate him/her?
Er, I guess so. Hmm. Well it looks like we need to be looking at the graphics animator https://sdk.play.date/2.4.2/Inside%20Playdate.html#_animation but before that I need to address the issue that our image has got four sprites in it. https://sdk.play.date/2.4.2/Inside%20Playdate.html#C-graphics.imagetable is what we need, an image table and more specifically a sequential image table. From the docs:
Sequential image tables are useful as a way to load up sequential frames of animation. They are loaded from a sequence of files in your game’s source folder at compile time from filenames with the suffix
-table-<sequenceNumber>
before the file extension. Individual images in the sequence are accessible via imagetable:getImage(n). The images employed by a sequential image table are not required to be the same size, unlike the images used in a matrix image table.
Ah no. That’s not what we need, we need a Matrix image table. With that we can load just one file and tell it the width and height of each sprite. We’re creating a tilemap! That’s exciting, I’ve always wanted to do that.
Matrix image tables are great as sources of imagery for tilemap. They are loaded from a single file in your game’s source folder with the suffix
-table-<w>-<h>
before the file extension. The compiler splits the image into separate bitmaps of dimension w by h pixels that are accessible via imagetable:getImage(x,y).
So what are my individual image dimensions? 40×40 according to the website. I could have worked that out for myself as the image size is 160×40 :). Soooo I need to call it cat_sprite-table-40-40.png I think.
error: source/images/cat_sheet-table-40-40.png: image size 500x125 isn't a multiple of the cell size, 40x40
Appears my image got resized during the dithering. Hmmm – that would give me a sprite size of 125×31.25 ?! Looks like the redithering has resized it. Tried again and it’s given me 400×100 which is better, that’s four lots of 100×100 so cat_sheet-table-100-100.png, here we go.
Some time later …
That turned out to be a wild ride in which I learnt a lot but got no closer to the final goal. Because all I wanted to do was get the animation running I cut a load of corners.
This code will show my animated cat. It’s not “right” but it does fulfill my goal and, as a I said above, a learnt a lot about the processes involved in doing it right. I have a lot to learn 🙂
import "CoreLibs/graphics"
local gfx <const> = playdate.graphics
local catSheet = gfx.imagetable.new("images/cat_sheet")
assert(catSheet, "Failed to load cat_sheet")
local count = 1
function playdate.update()
-- Animates the cat every five frames using our four images
count += 1
if count > 20 then
count = 1
end
image = math.ceil(count / 5)
gfx.clear()
local sprite = catSheet:getImage(image) -- Get the first image
assert(sprite)
sprite:draw(100, 100)
end
And here it is!