Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Tiled Map object not working

This thread is locked; no one can reply to it. rss feed Print
Tiled Map object not working
felipedacosta
Member #15,749
September 2014

Hey there,

So I decided to make a tiled map object inside my game but i cant get it to work properly :(

Here is my map.h

#SelectExpand
1class Map{ 2 private: 3 static const int mapMaxSize = 100; 4 int map[mapMaxSize][mapMaxSize]; 5 int mapSizeX,mapSizeY; 6 int blockSize; 7 char *fileName; 8 9 public: 10 static ALLEGRO_BITMAP *tileSet; 11 Map(char*,const char*); 12 ~Map(); 13 int getMapMaxSize() {return mapMaxSize;} 14 int getMapSizeX(){return mapSizeX;} 15 int getMapSizeY(){return mapSizeY;} 16 int getMapInt(int row,int col); 17 void setMapValue(int value,int row,int col); 18 void drawMap(int,int) const; 19 void setBitmap(ALLEGRO_BITMAP*); 20};

and here is my map.cpp

#SelectExpand
1#include "Map.h" 2 3Map::Map(char* file,const char* imageLoc){ 4 int loadX = 0,loadY = 0; 5 fileName = file; 6 blockSize = 128; 7 tileSet = NULL; 8 std::ifstream openfile(fileName); 9 if(openfile.is_open()){ 10 openfile>> mapSizeX >> mapSizeY; 11 while(!openfile.eof()){ 12 openfile>>map[loadX][loadY]; 13 loadY++; 14 if(loadY>=mapSizeY){ 15 loadY=0; 16 loadX++; 17 } 18 } 19 } 20 else{ 21 std::cerr<<"Erro loading map txt File"; 22 exit(0); 23 } 24} 25 26Map::~Map(){ 27 if(tileSet){ 28 al_destroy_bitmap(tileSet); 29 } 30} 31 32int Map::getMapInt(int row,int col){ 33 if(row<mapSizeX && col<mapSizeY){ 34 return map[row][col]; 35 } 36 else{ 37 return -255; 38 } 39} 40 41void Map::setMapValue(int value,int row,int col){ 42 if(row<mapSizeX && col<mapSizeY){ 43 map[row][col] = value; 44 } 45} 46 47void Map::drawMap(int posX,int posY) const{ 48 for(int i = 0;i<mapSizeX;i++){ 49 for(int j = 0;j<mapSizeY;j++){ 50 al_draw_bitmap_region(tileSet,map[i][j]*blockSize,0,blockSize,blockSize, 51 j*blockSize-posX,i*blockSize-posY,0); 52 } 53 } 54} 55 56void Map::setBitmap(ALLEGRO_BITMAP *tile){ 57 tileSet = tile; 58}

the problem is,when i call the drawMap function inside the main loop, it slow down the FPS really bad, and the event handler stop working.

After some tests, i realized the bitmap is the problem. If i create a bitmap inside the main, and pass it to the Map::drawMap function instead of using the member bitmap, everything works fine.

Why is this happening??? And how can I solve it?

thanks ;D

Arthur Kalliokoski
Second in Command
February 2005
avatar

I don't grok all that C++ stuff, but the difference is probably that you're creating the bitmap in the faster case after you've set a graphic mode. If you create bitmaps before setting the graphic mode, they're in system memory, and it's slow to copy back and forth, but the other way creates the bitmap in video memory, where the video card can get at it easily with its own special optimizations.

They all watch too much MSNBC... they get ideas.

jmasterx
Member #11,410
October 2009

Arthur is probably right, but also try:

al_hold_bitmap_drawing(true);
//nested for loop with draw calls
al_hold_bitmap_drawing(false);

This will avoid texture switching which is a pricy operation.

If you can, show us when you load the tiles.

Also, your map instance destructor destroys a static bitmap, that is evil my friend :o (don't let BamBam see that).

felipedacosta
Member #15,749
September 2014

Hey, thanks for the replies :) I tried both but none worked...

However after some tests, I figured out that if I create an instance of Map after I create a instance of ALLEGRO_BITMAP it works.

This works

//-------Variaveis---------
EventHandler *eventHandler = new EventHandler();
Player *player = new Player("PlayerSprite.png");
//-----------Variaveis Allegro----------
ALLEGRO_DISPLAY *display = al_create_display(WIDTH,HEIGHT);;
ALLEGRO_EVENT_QUEUE *fila = al_create_event_queue();
ALLEGRO_TIMER *timer = al_create_timer(1/FPS);
ALLEGRO_BITMAP *sprite = al_load_bitmap("PlayerSprite.png");
Map *mapa = new Map("TileMap.txt","TileSetTest.png");

this does not

//-------Variaveis---------
EventHandler *eventHandler = new EventHandler();
Player *player = new Player("PlayerSprite.png");
Map *mapa = new Map("TileMap.txt","TileSetTest.png");
//-----------Variaveis Allegro----------
ALLEGRO_DISPLAY *display = al_create_display(WIDTH,HEIGHT);;
ALLEGRO_EVENT_QUEUE *fila = al_create_event_queue();
ALLEGRO_TIMER *timer = al_create_timer(1/FPS);
ALLEGRO_BITMAP *sprite = al_load_bitmap("PlayerSprite.png");

anyone knows why???

and btw, jmasterx why is it bad to destroy a static bitmap?

thx

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

You should create ALL of your ALLEGRO_BITMAPS after you create your ALLEGRO_DISPLAY. If you don't, they will be memory bitmaps, and memory bitmap drawing in Allegro 5 is much slower than drawing a video bitmap with hardware acceleration.

One reason you don't want your tile map to be static is because each map should have its own tile sheet. It shouldn't share one between all of your maps. There may be a time soon when you want to have more than one map object, and then you wiil need your tile map to be non-static.

jmasterx
Member #11,410
October 2009

Yeah exactly, right now, if you load a tile set, then you create 3 maps, then you destroy 1 of the maps, your program will crash hard.

1) The object that creates a bitmap should 99% of the time be the one who destroys it. Your map DOES NOT create the tiles but it destroys it, very evil :) .

2) Like Edgar said, each map should have its own tile array. The map constructor can load the tile set, then the destructor would destroy it. The other way is something else creates the tile set and gives a pointer of the set to the map. But then that object is responsible for destroying it, not your map :P

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

To clarify what I said a little bit, you can have maps share tile sets, but then you don't want your map to be responsible for destroying them, as jmasterx said. Otherwise each map should have its own. This goes with the idea of object autonomy. Each object should be able to stand on its own, without dependencies on other objects. If information does need to be shared, then only use a reference, and leave ownership to the object the reference comes from.

felipedacosta
Member #15,749
September 2014

Got it!
Thanks for the help ;D;D;D

Go to: