Can someone please help me fix this so it doesn't segfault? I assume I'm missing something obvious, though. I assume the issue is something I'm missing about how std::vector works, but I thought that it copies the data.
This code is based on https://wiki.allegro.cc/index.php?title=Allegro_5_Tutorial
/Input .
std::vector will invoke the copy constructor (in your case, it is a simple memberwise copy because you don't implement a custom copy constructor), and then delete the original, when adding elements (because the backing array needs resized). Your destructor deallocates the image that the default copy constructor just copied.
Perhaps the easiest way is to fix this is make a std::vector of pointers to images. You'll have to manually deallocate the images, however, when necessary.
Is there a way to use the al_clone_bitmap thing?
I want dinit to be self managed. What about a stateful funtor holding the vector of Bitmaps that shuts itself down at the end?
Yes, you can make a deep copy of an ALLEGRO_BITMAP by using al_clone_bitmap, but why do you want to make copies of your images? It takes time and cpu and memory. You'd be better off using a vector of pointers to images that you add using new and destroy using delete.
ALLEGRO_BITMAP * newedBitmap = new ALLEGRO_BITMAP;
fails with 2 errors:
So I assume I can't actually new / delete them. :/
Also, what happens when you al_create_bitmap twice to the same pointer?
You can't create an ALLEGRO_BITMAP with new. You have to use one of the allegro functions. ALLEGRO_BITMAP is also an opaque struct so you can't access its members.
You can however new your Image class.
Wait. Why do I need to access its members to new? And rather, why would encapsulating it make this any better and work?
You don't need to access it's members. But the way that you make a struct opaque in C also means you can't access it's members or new/malloc it, since you don't know its size.
Encapsulating it makes it so people can't access the internals, and make it impossible for us to change internal things when we need to.
Also new wouldn't know how to "create" an ALLEGRO_BITMAP. an ALLEGRO_BITMAP is a C type, that requires certain members to be set in a specific way. C does not have constructors, or proper objects/classes for that matter, so you have to use functions that know how to create them. ie: al_create_bitmap.
Ok.
Why doesn't allegro internally have a linked list that gets added to on al_create_bitmap and is used during allegro's deinit such that al_destroy_bitmap isn't required?
al_destroy_bitmap() would be needed anyway, because graphic memory is a precious resource shared by your entire system.
If your game has very few graphics (ex: a Sokoban with many maps but always the same tiles), you can probably load all graphics at beginning and keep them until the game stops.
But for example a game with different graphics for each level (Ice world, Lava World, Haunted house etc.) should rather keep only one level in memory. While the graphics of the player character can be kept for the whole duration of the program.
Steam hardware survey says the average video card has 1Gb of ram.
If you use truetype font and "leak" the bitmap of the text every time you redraw the screen, you will run out, just by leaving the game idle.
My suggestion, as always, would be to use plain C and not C++ until you thoroughly understand both of them. Allegro is a C library, so you should understand C to use it. If you just know C++, then you don't know enough C to use Allegro, as the essential design of the two languages is fundamentally different.
C++ vectors require you to have a deep understanding of C++ to be able to use them correctly in all cases. C++ is often like that, on the face it looks easy to use, but to do anything that isn't a very simple construct correctly you have to know many fine details of C++.
Below and attached is a pure C solution that doesn't use any vectors but that makes specific types for games, namely Sprite and SpriteList. It's a bit longer than the C++ code, but now you have full control of what is going on, as well as the beginnings of a generic sprite list system that will be useful for many types of games. Not to mention that since C doesn't do anything behind your back, so it's easy to see what is going on.
This Spritelist also keeps track of all bitmaps allocated indirectly, so just calling spritelist_done will clean up the allocated sprites for you.
Got it working with C++ now. It has to be C++ because I do a lot with generic programming. Thanks!
PS. The C code in interesting and might be very useful for a different project. Is that code under the Allegro License?
Well, personally I don't need generics or C++ for anything, but if you got it to work then that's fine.
As for this C code, it's only a snippet, so feel free to use, modify, sublicense, etc. it in any way you like, under the Allegro license or any other open source license you might think of.
However, if you want a full tile and sprite engine look at my project here:
https://github.com/beoran/eruta
That is under the Sleepycat license, which is a copyleft, but simpler than GPL. You can do what you want but if you redistribute a modified binary version, you also have to redistribute the modified sources of the engine.