Search code examples
c++cairoallegro5

working with Cairo and Allegro 5


Newbie programmer here,

I am designing a 2d game using Allegro 5 and I have noticed that when working with bitmaps in allegro (png files exported from photoshop actually...) that rotated images look less than stellar: rotated meteor

The one on the left is in the original orientation and the one on the right is rotated 10 degrees. They're a little small but the difference in edge quality is clear.

First of all, I would really like to avoid creating a sprite sheet including all the different rotational positions for the following reason:

I have different 'effects' happening to meteors and all other objects I am creating that will require a glow around the object. I will be applying at least 6 different glowing colors around each object. Now each of these meteors will need to have maybe 30 frames of rotation to appear smooth. Lets say I want a measly 10 different object in the game that work like this; that's 1800 files just for those objects!

I would rather focus on finding a better way to display rotated images than taking the time to do that.

I've tried researching various photoshop techniques but the best I can come up with is make the circle in photoshop slightly smaller and then have it 'glow' the same shade of gray which sort of solves the rotation problem but it makes the meteor look fuzzy.

I then did some more research and discovered that various blending options are available in Allegro 5. I have tried all possible options in al_set_blender - none of them address the issue of the jagged edges.

Finally, I searched again for how to deal with this and discovered this post about anti-aliasing in Allegro 5. As was pointed out in the answer there is an anti-aliasing option available, but with the major restriction of only working when drawing primitives to the back buffer. Actually implementing this would be a ton of work and it seems quite inefficient to draw all the required primitives every single time.

What caught my attention in the other post, however, was this comment:

As an aside, if you don't need realtime performance for a game, you could also hook into libcairo to draw nice looking vector graphics. It's extremely simple to hook it into Allegro, but that's a different topic.

So again I did my research on graphics libraries and how they might solve my problem. I looked at Cairo, SDL, Qt, ImageMagic, among others, but in the end I agreed that Cairo appears to be the right tool for the job.

And finally we arrive at the reason for this post:

My question is: How can I "hook Cairo in" to Allegro 5?

Now, I haven't done any work with Cairo, so I'm not tied down to it, but I would like to keep using Allegro, unless there are really good reasons for switching to something else.

Allegro has a simple and straightforward way of creating a display and drawing to it using allegro commands. But Cairo has its own way of doing things, and it seems that Cairo doesn't manage the display at all. The only way I can imagine the two working together is Cairo receiving drawing commands, drawing the image, saving the image as a png file, and then having the allegro function open and read in that file for 1 frame. This can't be what the commenter was getting at.

Anyways, feel free to criticize my thought process. I will not be offended. If there is something simple you think I have not understood, please enlighten me.


Solution

  • Cairo can render to a block of memory, which can be transfered into an Allegro bitmap. However, performance would not be acceptable for a real time game. It would be more useful for drawing charts, loading SVG images into static bitmaps, etc. Performance aside, I don't see how it helps with rotating bitmaps anyway.

    The "anti aliasing" that you speak of only applies to primitives. So that question you linked to is not relevant. These options might help if used before creating / loading the rotating bitmap:

    al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR | ALLEGRO_MIPMAP);
    

    They generally apply to scaling bitmaps, but your rotation may qualify.

    Lastly, using pre-multiplied alpha (the default blender) will give you better results.

    I just tested this with your image:

    #include <allegro5/allegro.h>
    #include <allegro5/allegro_image.h>
    
    int main()
    {
      ALLEGRO_BITMAP *circle;
    
      al_init();
      al_init_image_addon();
    
      al_create_display(640, 480);
    
      al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);
    
      circle = al_load_bitmap("circle.png");
      if (!circle) return 0;
    
      al_clear_to_color(al_map_rgb(0,0,0));
      al_draw_bitmap(circle, 100, 100, 0);
    
      al_draw_rotated_bitmap(circle, 25, 25, 200, 200, 0.174, 0);
    
      al_flip_display();
    
      al_rest(5);
    
      return 0;
    }
    

    I believe it gives you the desired look.