Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » BITMAP pointer disappears in the map??

This thread is locked; no one can reply to it. rss feed Print
BITMAP pointer disappears in the map??
armond
Member #8,282
January 2007

Hi guys! I have an Animation class, a class that has static members and serves as the main point of entry to play the game and other classes such as enemies. Now, I also have a BitmapManager class which looks like this.

please see attachment bitmapmanager.cpp

and the Animation class looks like this.

please see attachment animation.cpp

and before, when I create an instance of the animation class, I would do something like this...

flyingAnimation = new Animation(BitmapManager::addBitmap("ASTEROID_SPRITE_FLYING", "graphics/asteroid_flying.bmp"), 10, 4, BY_WIDTH);

but I thought it was too heavyweight because my addBitmap makes a call to

BITMAP* bitmap = load_bitmap(fileName, NULL)

everytime the function addBitmap is called. So I thought I'd change my strategy and just load the bitmap first.

In my PlayState class(a singleton, this is being put in a state stack) constructor, I load these images

please see attachment playstate.cpp

So instantiating an Animation object is now changed from

flyingAnimation = new Animation(BitmapManager::addBitmap("ASTEROID_SPRITE_FLYING", "graphics/asteroid_flying.bmp"), 10, 4, BY_WIDTH);

to

flyingAnimation = new Animation(BitmapManager::getBitmap("ASTEROID_SPRITE_FLYING"), 10, 4, BY_WIDTH);

Now here is where the problem occurs, in the loadLevel function, when I instantiate an Enemy using a factory it would seem that I'm referencing to a NULL object and my game crashes. How can this be? Before any instance of the Enemy class is created, the BITMAP(ASTEROID_SPRITE_FLYING) is in the map. Then suddenly, when I instantiate an object it's gone(NULL)! I can see if the BITMAP* pointer points to something or NULL because I have a cout statement.

BITMAP* BitmapManager::getBitmap(char* key)
{
std::cout << "BITMAP: " << key << (bitmapTable[key] == NULL ? " NULL" : " SOMETHING") << std::endl;
std::cout << key << " is " << ( lookupBitmap(key) == true ? "EXISTING\n" : "NOT EXISTING\n");

return bitmap;
}

Here is the code for my Enemy, actually asteroid class(there is nothing in the Enemy class but an empty destructor).

please see attachment asteroid.cpp

Please help guys... Thanks!

Simon Parzer
Member #3,330
March 2003
avatar


    if ( bitmapTable[key] != NULL )

This may or may not work. It's the wrong way for sure.

Use

return bitmapTable.find(key) != bitmapTable.end();

armond
Member #8,282
January 2007

Thanks! Although my code is a little stubborn, I did your suggestion.

1BITMAP* BitmapManager::getBitmap(char* key)
2{
3 std::cout << "BITMAP: " << key << (bitmapTable.find(key) == bitmapTable.end() ? " NULL" : " SOMETHING") << std::endl;
4 std::cout << key << " is " << ( lookupBitmap(key) == true ? "EXISTING\n" : "NOT EXISTING\n");
5
6 //return bitmapTable[key];
7 std::map<char*, BITMAP*>::iterator it = bitmapTable.find(key);
8
9 BITMAP* bitmap = it->second;
10
11 return bitmap;
12}
13 
14bool BitmapManager::lookupBitmap(char* key)
15{
16 if ( bitmapTable.find(key) != bitmapTable.end() )
17 {
18 return true;
19 }
20 else
21 {
22 return false;
23 }
24}

my bitmapTable indeed returns NULL... Do you guys see any more problems? Thanks!

Matthew Dalrymple
Member #7,922
October 2006
avatar

Quote:

std::cout ...

Are you using this in a console window?

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

X-G
Member #856
December 2000
avatar

Use the code tags. Also, this is way too much code to dredge through; post, inline, the samples relevant to all map manipulation.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

James Stanley
Member #7,275
May 2006
avatar

May be irrelevant, but Allegro defines key. It may be using Allegro's not yours, dunno.

armond
Member #8,282
January 2007

Thanks guys!

Yes, I use std::cout to output in console window.

Here's how the map is manipulated...

I insert something by calling this method

BITMAP* BitmapManager::addBitmap(char* key, char* fileName)
{
    BITMAP* bitmap = load_bitmap(fileName, NULL);
    
    bitmapTable.insert( std::pair<char*, BITMAP*>(key, bitmap) );   

    return bitmap;
}

and try to get that inserted value(pointer) by calling this method

BITMAP* BitmapManager::getBitmap(char* key)
{ 
    std::cout << "BITMAP: " << key << (bitmapTable.find(key) == bitmapTable.end() ? " NULL" : " SOMETHING") << std::endl;
    std::cout << key << " is " << ( lookupBitmap(key) == true ? "EXISTING\n" : "NOT EXISTING\n");
    
    //return bitmapTable[key];
    std::map<char*, BITMAP*>::iterator it = bitmapTable.find(key);
    
    BITMAP* bitmap = it->second;
    
    return bitmap;
}

Now, I have an Asteroid class which has an animation class in it. From here, I would use the ASTEROID_SPRITE_FLYING which was already inserted in the map before any object that might use the BITMAP is instantiated.

Asteroid::Asteroid(int x, int y, int w, int h, int sp, Status stat)
{
    this->x = x;
    this->y = y;
    width = w;
    height = h;
    speed = sp;
    status = stat;

    flyingAnimation = new Animation(BitmapManager::getBitmap("ASTEROID_SPRITE_FLYING"),  10, 4, BY_WIDTH);
    //dyingAnimation = new Animation();
    currentAnimation = flyingAnimation;
}

Now, the error seems to be in the Animation class, if you try to print from the Asteroid constructor for even a hundred times, you can still see that the inserted BITMAP pointer in the map with the key ASTEROID_SPRITE_FLYING is still there. But once the flingAnimation is instantiated, it's gone.

1Animation::Animation(BITMAP* bitmap, int frameDelay, int maxFrames, FrameExtractionMethods extractionMethod)
2{
3 this->frameDelay = frameDelay;
4 this->maxFrames = maxFrames;
5
6 currentFrame = 0;
7 frameTick = 0;
8
9 //get bitmap dimensions
10 int bw = bitmap->w;
11 int bh = bitmap->h;
12 
13 //set frame dimensions
14 int frameWidth = (int)bw / maxFrames; //e.g. 200 / 4 == 50
15 int frameHeight = bh;
16
17 //EXTRACT IMAGES BY_WIDTH
18 int currentX = 0; //to determine the extraction coordinate
19
20
21 for (int i = 0; i < maxFrames - 1; i++)
22 {
23 animationFrames<i> = create_sub_bitmap(bitmap, currentX, 0, frameWidth, frameHeight);
24 currentX += frameWidth;
25 //std::cout << "currentX: " << currentX << "\n";
26 }
27
28
29}

the Animation class would crash my game. However, by trying to atleast omit the use of the BITMAP pointer that is in the Animation class's constructor(e.g. changing int bw = bitmap->w to int bw = 128), the crash would disappear... But then, it would render my class useless. I hope you guys get the idea now ;D

X-G
Member #856
December 2000
avatar

Quote:

std::pair<char*, BITMAP*>(key, bitmap)

This is your problem. Using a char * for a key is a bad idea, because comparing two char pointers doesn't work the way you expect it to. When you insert it, you pass it a pointer that points to some chunk of data containing the word, say, "foobar". But the next time you try to take it out, you pass it a different pointer pointing to some other chunk of data. The fact that both "contain" the word "foobar" is irrelevant; the map just compares the pointers themselves.

Your solution is to use std::string, which overloads the relevant operators, making it do what you expect it to:

std::map<std::string, BITMAP*>

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

armond
Member #8,282
January 2007

THANK YOU SOOOO MUCH! Now I can sleep early with a smile on my face! Thanks!

BTW, I changed the key to an enum instead of std::string for easier maitenance. :)

Go to: