Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » c++ design...

This thread is locked; no one can reply to it. rss feed Print
 1   2 
c++ design...
lucaz
Member #4,194
January 2004

hello,
in my game, Ive a base class enemy:

class enemy {
 int x, y, r;
 int speed;
 bitmap image;
public:
 ...
};

then, i make new enemies classes like:

class darkstar : public enemy { ... };

the problem is that ALL darkstar have the same image, and this way im using a lot of RAM.
so, since i dont like to use globals I redesigned the classes:

class enemy {
 int x, y, r;
 int speed;
public:
 virtual get_image() = 0;
 ...
};

class darkstar : public enemy {
 static bitmap image;
};
bitmap darkstar::image("mybitmap.bmp"); // this constructor loads a bmp

1)Is this a good design?
2)I cannot load the bitmap image for "darkstar", because the allegro wasnt initialized yet.
This is a big problem!, Im thinking about
a)call allegro_init(); by int cheat = allegro_init(), at first (i dont like this way...)
b)create a one time constructor for darkstar class:
darkstar() : enemy() {
static bool init = false;
if(init) return;
init = true;
image.load("mybitmap.bmp");
}

Help!!

Frank Drebin
Member #2,987
December 2002
avatar

Quote:

since i don't like to use globals

i think it's a good idea to use as few gloabls as possible but here is a point where a global BITMAP* would be the best thing.
in this case you don't need a var in the classes for holding the bitmaps.

Daniel Sauder
Member #4,762
June 2004

If you use pointers for the BITMAPs allegro don't have to init... and if you don't wanna use globals you can load the image in your enemy manager class ;)

Trezker
Member #1,739
December 2001
avatar

Rick
Member #3,572
June 2003
avatar

I always have a manager class, that is a singleton, to load in bitmaps. Then just pass them around. That way they are only loaded once.

========================================================
Actually I think I'm a tad ugly, but some women disagree, mostly Asians for some reason.

decsonic
Member #4,150
December 2003

Yup, IMO A Resouce manager is the way to go, have a unique key for each bitmap, (like 4 digits represents the file, and 2 digits the resource index).

cool thing about this its easy to optimize the memory usage, like loading as the bitmaps are requested, keep a reference count and release them as no entities are using the resource.

Programmer's paranoia: Don't trust anybody's code, not even your own.

Human Modeling Tutorials

lucaz
Member #4,194
January 2004

mnnn, the idea is have a class with ALL the game data, and when any object needs it, it calls the singleton?

class singleton {
 bitmap darkstar_image;
 ...
} singleton;

it needs to be global, right?, (i think I dont understand :-[ !)

CascoOscuro
Member #4,966
August 2004
avatar

you are including a bitmap for each enemy object.
So, if you have 500 enemies with the same bitmap you will have 500 cloned bitmaps.
It's better to store enemy bitmaps in a array; then, in your enemy class, use an index for the enemy bitmap array.

decsonic
Member #4,150
December 2003

A Singleton is a design pattern usfull when you only need a single instance of a class.

Making tons of singleton bitmaps is bad a design IMHO ;).
Also why not make the classes a bit more generic?

Make the BigBad Villan an instance of a Enemy class instead of making the BigBad villan a class himself :)

Programmer's paranoia: Don't trust anybody's code, not even your own.

Human Modeling Tutorials

lucaz
Member #4,194
January 2004

Quote:

Make the BigBad Villan an instance of a Enemy class instead of making the BigBad villan a class himself

in this way, the Enemy class needs a BITMAP** instead of BITMAP*, right?
if i wanna 2 BigBadVillans...

Rick
Member #3,572
June 2003
avatar

Quote:

So, if you have 500 enemies with the same bitmap you will have 500 cloned bitmaps.

Cloned, is a bad word to use here. You will have 1 bitmap loaded into memory and point it to 500 different enemies.

Example of what I do.

CTilesetManager class. This class loads in all bitmaps needed to my map.

CTile class. This class holds bitmaps to show.

CMap class. Holds 2D array of CTile and a CTilesetManger instance. So CTileManager in not global.

not workable but giving the idea:

1class CTilsetManager
2{
3 vector<BITMAP*> Tile;
4 void Load();
5 BITMAP* GetImage(int Index);
6};
7 
8class CTile
9{
10 BITMAP* Image;
11};
12 
13class CMap
14{
15 CTilesetManager tsmgr;
16 CTile map[10][10];
17 CMap()
18 {
19 CTilesetManager.Load();
20 }
21 void Load()
22 {
23 read(index);
24 map[0][0].Image = tsmgr.GetImage(index);
25 }
26};

========================================================
Actually I think I'm a tad ugly, but some women disagree, mostly Asians for some reason.

decsonic
Member #4,150
December 2003

Quote:

Make the BigBad Villan an instance of a Enemy class instead of making the BigBad villan a class himself

in this way, the Enemy class needs a BITMAP** instead of BITMAP*, right?
if i wanna 2 BigBadVillans...

If each entity managed its own resources yes, hence take that privlige away and make a resouce manager ;)

<code> BITMAP ** <code> is a double pointer (Pointer to pointer) and isnt realy needed.
you can have one pointer pointing to an address, or 10 000 pointing to an address(Wouldnt go for that kind of design tho ;) ).

Programmer's paranoia: Don't trust anybody's code, not even your own.

Human Modeling Tutorials

23yrold3yrold
Member #1,134
March 2001
avatar

My system is a small API based around a std::map<string, BITMAP*>. So every time a, say, goblin is created, in its constructor it asks the API for image "goblin". Which the API happily returns a pointer to.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

gillius
Member #119
April 2000

I think I did that in one of my games. I can't remember if I did the map lookup at the start of the level or at every creation. Do you have issues with performance there, 23?

Gillius
Gillius's Programming -- https://gillius.org/

23yrold3yrold
Member #1,134
March 2001
avatar

Performance issues? Nah. Obviously, maps are built for fast searching, so a string coughs up a bitmap ASAP. And then the object has the pointer, so performance is kinda a non-issue. Or am I not understanding you?

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

gillius
Member #119
April 2000

No you understood me. If you have game objects created often enough, it can become an issue. That's what I was asking.

Gillius
Gillius's Programming -- https://gillius.org/

23yrold3yrold
Member #1,134
March 2001
avatar

I create most of the objects betwen levels, but also a lot during the game (bullets, fire particles from the flamethrowers, etc). Hasn't been an issue yet ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Korval
Member #1,538
September 2001
avatar

A resource manager is a good idea, but it should also, in addition to lookup by name, provide safe pointer access to that resource. That way, you look it up only when you instantiate a character of that type, and when that entity uses the object, it just dereferences the safe pointer. While this dereference operation is slower than a regular pointer dereference, it is faster than a map search.

Trezker
Member #1,739
December 2001
avatar

Quote:

it needs to be global, right?

A singleton class is globally available, but you can't make any instances of it outside of the singleton class itself, so there cannot be any global instances of it. Instead you ask the class to give you a reference to an instance that you can use.

lucaz
Member #4,194
January 2004

i like the std::map<> idea instead of singleton class.
can you write some code?, this is my code:

map<string,void*> Data; // need to be global, right?

class X {
 BITMAP* image;
public:
 X() { image = (BITMAP*)Data[typeid(*this)]; }
};

is this similar to have a global BITMAP*?

Oscar Giner
Member #2,207
April 2002
avatar

It's not good design to have void pointers. The correct way would be to have a base class from where other classes inherit. Then you store pointers to this base class.

You can have a singleton map. It's actually an OOP design pattern, and it's called a dictionary. Using my singleton class from the thread linked by Trezker:

class BitmapDic : public map<string, BITMAP*>, public Singleton<BitmapDic>
{
// nothing here :)
};

[edit]
Or even cooler, you can have a dictionary class:

template <typename K, typename T> class Dictionary: public map<K,T>, public Singleton< Dictionary<K,T> >
{
};

And, to create a dictionary of BITMAP's, with string keys:

class BitmapDic : public Dictionary<string, BITMAP*>
{
};

;D

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

// need to be global, right?

Nah. I just keep it as a static variable in one source file and write a few functions for interacting with it. So ...

class X {
BITMAP* image;
public:
X() { image = GetResourceImage("fhqwgads"); }
};

My variable is a map<string, BITMAP*>, of course. :) I also have a map<string, CAnimation*> with a similar API (GetResourceAnimation() ...)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Don Freeman
Member #5,110
October 2004
avatar

Make your BITMAP data in this class to be static. Since they all use the same image, it is pointless to have more than one copy of the same image...right?::)

class Enemy
{
public:
Enemy(){pImage=NULL;}
~Enemy(){if(pImage){delete pImage;pImage=NULL;}}
int LoadImage(char *pFileName)
{
pImage = load_bitmap(pFileName,NULL); // truecolor doesn't
// need pallete
if ( !pImage )
return -1;
return 0;
}
static BITMAP *pImage;
};

Simply call LoadImage() after you initialize allegro and setup the graphics system and all will work just fine!;)

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

lucaz
Member #4,194
January 2004

im not sure of this: but an extern variable doesnt become global when you call it?.
for example, allegro::screen is extern, but isnt exactly like if it where global? (cin and cout too)

Quote:

Make your BITMAP data in this class to be static. Since they all use the same image, it is pointless to have more than one copy of the same image...right?

what?, i dont understand
there only one BITMAP* image per class. (doesnt matter the number of instances )

ImLeftFooted
Member #3,935
October 2003
avatar

Extern isnt related to scope. Extern creates a 'fake' variable so that code can be compiled assuming the variable exsists, not really of much concern with this problem.

I think it might be a better idea if the OP just used the datafile system. Dictionaries and map<>s can be a bit complicated to understand and implement, and if the OP is okay with hardcoded image input (which it appears he/she is) it would make his/her life a lot easier.

Edit:
Its a good idea to add 'Edit' tags if you add something to your post.;)

 1   2 


Go to: