Help with rotating images

Hey, I am making a top-secret game (Sneak peeks coming soon!) and I need some help with rotating sprites. Basically, let’s say we have a 16*16 sprite:
example
Now, if I wanted to rotate this, what I would usually do is I would just use Paint to rotate the image in all four directions like so:
example2
This has one disadvantage, which is that I would have to store every single sprite in every single direction. I was wondering if there was any way to rotate sprites without having to do the above, as this would help me heaps. (I only need the image to be rotated by 90, 180 and 270°)

Any help would be highly appreciated!
Thanks.

if you only need the four cardinal directions you could change the rendering order of the sprite.

You can do this by changing in which way you render the sprite 0 to max x produces a different output to max x to 0 and so forth

Edit: off the top of my head I think this question has been asked before?

Edit 2.0: Yea it has @filmote has written some code to help try having a look inside sprites.cpp https://github.com/filmote/RotateImages

I think its broken!

You are better of looking at ArdBitmap - this does rotations and a lot more!

3 Likes

Thanks, @filmote and @Dreamer2345, I just hade a quick look through the source code of ArdBitmap and I didn’t spot anything to do with rotation? I can use mirror, but later on i might need to rotate images too. :wink:

A flip both vertically and horizontally equals a rotate by 180 degrees. That at least halves your images!

But I see, no real rotation.

My solution - I might have to go back and fix it - rotated images in memory and used customised draw functions to draw it from memory. It could only work on 16x16 images from memory.

1 Like

That would be pretty much what I need, seeing as the game is based around 16*16 tiles on a map. Thanks! :grin:

Can you make do without the code for a short while? As I said, I need to go back and fix it as I think I broke it and moved on.

Yes, that will be fine.

1 Like

Its working and in my repo here > https://github.com/filmote/RotateImages

There are bugger all comments but you will see in the sample INO that I take an image and mask from PROGMEM and rotate them around 90, 180 and 270 degrees in memory and render them using the modified drawOverwriteRAM() and drawExternalMaskRAM() functions.

There are a couple of rotate functions and you can see that I can rotate an image from progmem or RAM into a predefined output array in RAM. This is then used for rendering. Likewise, I can rotate a corresponding mask using the same functions.

I have not done any performance testing but imagine that its not particularly fast. I hope your game is not one that needs absolute speed.

1 Like

Flash isn’t that much slower than RAM if done properly. I believe it’s 2 cycles vs 3 cycles… (for just the data access)… so by the time you add in all the rotation, etc… that starts to be very minimal. So it wouldn’t necessarily have to be done in RAM.

How many are you expecting to have?
The size of the code needed to actually do the rotating could outweight the cost of the number of sprites you’d need if you’re only going to need a handful.

Sorry, what I meant is that if you are regularly rotating an image from progmem into RAM before rendering, it could slow the code down significantly. The code has not been optimised in any way.

Depending on the game you are building, you may be able to rotate the image when the user (say) changes direction and use it for many cycles. If you are planning on using a tile set and have to rotate many images just to render a screen, it is probably not going to be efficient.

Yes … a very good question. My code isn’t big but it is also taking additional RAM to support the rotated images.

One enhancement that could be done is to rotate the image and render it straight into the screen buffer without staging it into an array in RAM. I chose not to do this as the game I was working on at the time fit into the first category (rotations occurred infrequently) and I wanted to save on multiple rotations.

1 Like

I can think of a very easy way to do that, but it’s also probably one of the slowest ways.

The Arduboy’s odd image format and lack of barrel shifter makes this kind of image manipulation pretty slow by nature.

Flip (horizontal) is easy, rotate is HARD.

I sort of get it… but to me that is a strange case… there is so MUCH less RAM available than flash… so assuming you have extra space to store the rotated version in RAM but NOT in flash is interesting. If it was only a single key sprite you needed (player sprite, etc) it seems many times it’d make more sense to store the rotated versions in the more more numerous flash.

Plus there is the cost of the rotation code itself… vs the cost of just storing the rotated assets (if it’s only a few). And if it’s a ZILLION sprites…

Exactly.

Nah, it’s easy. :P

auto sinA = sin(angle);
auto cosA = cos(angle);
auto destinationX = (sourceX * cosA) + (sourceY * -sinA);
auto destinationY = (sourceX * sinA) + (sourceY * cosA);

auto pixel = getPixel(bitmap, sourceX, sourceY);
arduboy.drawPixel(destinationX, destinationY, pixel);

But horribly, horribly slow.

Slightly more seriously, for 90 degrees sin(90) is 1 and cos(90) is 0 so that all reduces to:

auto destinationX = -sourceY;
auto destinationY = sourceX;

auto pixel = getPixel(bitmap, sourceX, sourceY);
arduboy.drawPixel(destinationX, destinationY, pixel);

Which is still horribly slow, but much less so.

The hard part is just the actual optimisation.

1 Like

I obviously meant computationally HARD. :stuck_out_tongue:

I’m not aware of any great ways to optimize a rotate - are you? No matter what you do seems your stuck being a LEAST an order of magnitude slower than just memcpy(from: flash, to: VRAM) (ok, I guess drawBitmap is a BIT more complex, but that’s the simple aligned case)… might be fast enough for some uses, but still VERY slow by comparison.

I can think of at least one (before accounting for the destination not being column-aligned),
which is to cache 8 columns from the source so you can shift the bits out of them into a single column in the destination.

I did something similar to optimise the rendering in my (still work in progress) port of Arduboy2 for the Pokitto.
(The code just reformats the Arduboy2 buffer into the Pokitto buffer’s format.)

Accounting for not being column-aligned would complicate matters somewhat,
but there’s probably something that can be done.

memcpy would probably be slower than a for loop. :P


On the bright side, a 180 degree rotation should be almost as cheap as regular bitmap drawing.

Thanks for all the feedback, guys! I think I may need to clear some things up, though:
I aren’t really bothered about speed, as the game is meant to look ‘8 bitty’ like an arcade game.
Also, I am probably going to have a fair amount of sprites, but the game itself should be quite small in terms of memory.

1 Like

If at all possible, I would stick with actually creating pre-rotated images in PROGMEM. My code is based on an older version of the Arduboy2 library and there have been a number of updates since then. If you run into trouble then others can help…

If you cannot squeeze all your images into memory then resort to my code.

Okay, Thanks!

1 Like