I'm developing a game with JavaScript and HTML5 and I'm wondering about the performance implications of sprite rotations. There are two ways that I know to rotate a sprite:

Rotate the actual sprite based on its rotational speed and velocity, as it travels along it's trajectory.

Pre-compute the rotations and store them as frames within the sprite sheet to give the illusion that it's spinning when it isn't.

On one hand, I can see how rotating some sprites in a spritesheet would be efficient because it's one image that is loaded, split into frames, and re-used. But on the other hand, I'm not sure the calculations involved for rotating the sprite based on its velocity and rotational speed are really anything for current browsers (on computers and mobile devices) to worry about.

In my game, the canvas area is 800 x 600, and the game is using 32 x 32 sprites for everything. The "map" isn't tile-based. Of the two options above, which would be more efficient for runtime performance?

3 Answers
3

From a pure quality standpoint, it would be better to serve a spritesheet with all the rotation angles. This allows you to make some adjustments for perspective and light direction for all angles which you can hardly do automatically (unless you have a 3d model). But even when you choose not to invest this additional work into the graphics and do the rotation automatic, graphic editors usually use filter algorithms with a much higher quality than those provided by implementations of the HTML5 canvas, resulting in less loss of quality.

But in case of web-based games, there is also another important consideration: Bandwidth. When you create an installable game, filesize usually doesn't matter that much. But when all assets are loaded from the web when the game starts, it pays off to keep filesizes small, because it results in much faster loading times. And loading times on web applications do matter a lot. Web users are impatient, and every second of additional loading time causes some percent of people to click the close-button of their browser tab. Also, most webhosting plans bill you by the amount of traffic you generate, so saving filesize saves you money.

When you have only one frame for each sprite which you automatically rotate in 8 directions on the client, you reduce filesize and thus loading time to one eight. This can mean that the loss of visual quality can be an acceptable trade-off.

But that does not mean that the performance of the game itself has to suffer. Instead of re-rotating the sprites whenever you draw them, you can precalculate the spritesheet with all the directions to an invisible background canvas at startup. This approach is a trade-off of memory for processing power. But unless you have a really hight number of rotation angles, it should be worth it.

Pre-rendering rotated sprites is probably not helping a lot in this case since most modern browsers use hardware acceleration for things as simple as 2D transformations.

It may be worthy in some very specific cases, like the one described in Josh Petrie's answer, or when you want to have a specific visual style, like "8 bits pixel art graphics", but unless you have a very good reason, I wouldn't recommend it.

Also pre-rendering rotated sprites have some downsides:

Bigger memory footprint (using too much memory is more likely to slow down your browser game than using GPU for rotating small images)

While most gaming framework handle rotations natively, you will have to add some code to find the right sprite for a given angle, which means more complexity, more potential bugs and more expensive code maintenance (You will also have to re-implement basic things like angular speed or angular acceleration if your game need them)

Cutting angles: if your sprites use the "corner pixels" (ie the ones near the top left corner) and you rotate the sprite by 45 degrees, those pixels will be out of the resulting 32x32 sprite; This will prevent you to use the full 32x32 area of your sprites for drawing, which may be annoying... On the other hand, if you draw your square 32x32 sprite with a 45 degrees rotation in your canvas, it will be complete.

Bottom line: I would say it really depends if you want to develop a game, or a gaming framework. As long as your framework offer things like rotation for free, and you don't have any specific issue with their implementation, just use it.

Also, unless you choose a framework which has been discontinued for years, it's likely that a group of motivated and talented peoples have spent a lot of time optimizing things as trivial as sprites rotations.

If your sprites are high-fidelity (for example, 3D models rendered into a 2D sprite sheet), than you probably want to encode the rotations into the spritesheet. Not for reasons of performance, but because the sprite probably will not look as good if you rotate it at runtime.

If your sprites are such than they can survive such a runtime rotation acceptably, then that is going to be the more efficient solution in most cases. This is because:

The math involved to rotate an image is not complex (basic trigonometry, possibly some matrix operations depending on the underlying frameworks involved).

The math is probably being done anyway (especially if you are using a framework that supports it, or supports hardware acceleration), so there's no effective cost to change the rotation value from 0 to whatever you need.

You will consume less memory in your spritesheets. At some level this may impact performance positively (less time spent paging, or better cache locality, et cetera), but mostly it is its own benefit.

It's much easier for the developer to implement and iterate on than baking the rotations, which requires the time-consuming (relative to the alternative) re-rendering process. You can trivially adjust rotation speed and amount, which is much harder if you pre-render all rotation frames.

You probably should only consider pre-baking the rotation frames if profiling has shown this to be advantageous (this may be true in a non-hardware accelerated situation, for example) or if your sprites need it to have acceptable visual quality.

Keep in mind that you can easily trade memory for better performance by caching. You draw each rotation-angle to a background canvas and keep it around for the next time you draw the same sprite with the same rotation.
–
PhilippJan 31 '14 at 22:05