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:
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:
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°)
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.
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.
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.
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.
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…
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.
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.