Looking for recommendations for how to pre-render rotated images

I am planning on rotating a fairly large image (half width of the screen). I'm looking for recommendations.

  1. Is there a recommended piece of software that makes saving the images easy? Should I do it in code?
  2. How many images should I save? Is 360 too many?
  3. Should I import all the images as an graphics.imagetable? That many images seems... heavy.

Anyone have any code snippets for any of this? Especially saving out the rotated images, but updating the image along with the (absolute) crank position would also be appreciated.

  1. if you have everything in a game already then writing a little extra code to export the rotated frames is the way to go.
  2. depends on your frame rate and size of graphics. I have small sprites, with 11 variations and two states, run at 60fps and went with 90 rotations. 360 worked but it took a lot longer for me to render the frames (inside an external workflow) and the difference wasn't huge in smoothness.
  3. Yes. Each of my car sprites is an imagetable with 3960 (1980x2) sprites in it. No problem!

I wrote about this on my blog:

1 Like

I just watched your Tiny Yellow Machine interview, and it sounds like maybe your "sprite studio" would help me with this task! (If it doesn't do the rotation piece, maybe it should, but even if it didn't, I'm also planning to move stuff around the screen while the rotation is happening, so it would help with that.)

Just for context, here's a mockup of what I'm planning:

mm-menu-v2

This is on the main menu for my game.

Really liked the interview, btw. :smiley:

1 Like

Glad you enjoyed the interview! It was a lot of fun.

I'll be working on the animator app this week and I'll put rotation on my to-do list. I can't promise it, as I'm worried about feature creep, but I'll try my best!

Without rotation you could choose the pre-rotated frames and seek to a position in the animation. I'll also keep that example in mind.

1 Like

This could use improvement, but works:

import 'CoreLibs/graphics'

local gfx = playdate.graphics

gfx.setColor(gfx.kColorBlack)

local single_image = gfx.image.new("test_image")
local rotation_resolution = 72

function playdate.update()
    if rotation_images then
        --gfx.clear()
        local select_image = nil
        if playdate.isCrankDocked() then
            select_image = 1
        else
            local crank_angle = playdate.getCrankPosition()
            local segment_angle = 360 / rotation_resolution
            select_image = math.floor((crank_angle + (segment_angle / 2)) / segment_angle) + 1
        end
        rotation_images:getImage(select_image):drawCentered(200, 120)
    else
        rotation_images = makeRotationImageTable(single_image, rotation_resolution)
    end
end

function makeRotationImageTable(image, segments)
    local w, h = image:getSize()
    local max_wh = math.floor(math.sqrt(w * w + h * h)) + 1
    local image_table = gfx.imagetable.new(segments + 1, max_wh, max_wh)
    local image_index = 0
    for angle = 0 , 360, 360/segments do
        image_index += 1
        local rotated_image = gfx.image.new(max_wh, max_wh)
        gfx.lockFocus(rotated_image)
        image:drawRotated(max_wh/2, max_wh/2, angle)
        gfx.unlockFocus()
        image_table:setImage(image_index, rotated_image)
    end
    return image_table
end

rotation_imagetable

1 Like