Search code examples
dictionarytileslagframe-rateallegro

Allegro 5: Tile Maps -> Scroll lag


I am currently working on a little Game im making

Now I've made a map via Tiled map Editor and put it on the screen via a al_draw_bitmap_region loop. The map is shown on the screen, yet when i try to scroll the view, it takes ages until it goes forward. This is probably caused by the "large" map (100x100) -> in Allegro 4 i used this method once, too and it worked fine for me (i used to blit everything in the doubleBuffer and blit it on the screen)

Yet I seem to not find a solution for my problem in allegro 5 so far I'm sorry if a board like this has already been open, I didnt found a solution for my problem so far.

I'd be really thankfull for help!

Code:

main.cpp:

#include<allegro5\allegro.h>
#include<allegro5\allegro_native_dialog.h>
#include<allegro5\allegro_primitives.h>
#include<allegro5\allegro_image.h>
#include<allegro5\allegro_font.h>
#include<allegro5\allegro_ttf.h>
#include "global.h"
#include "map.h"

using namespace std;



int main()
{

    ALLEGRO_DISPLAY *display = NULL;
    al_init_primitives_addon();
    al_init_image_addon();
    al_init_font_addon();
    al_init_ttf_addon();
    al_init();

    ALLEGRO_FONT *font18 = al_load_font("arial.ttf", 18, 0);

    if (!al_init())
    {
        al_show_native_message_box(NULL,NULL,NULL, "Could not initialize Allegro 5", NULL, NULL);
    }


    bool keys[] = {false, false, false, false};
    enum KEYS{UP,DOWN,LEFT,RIGHT};

    ALLEGRO_TIMER *timer = NULL;

    bool done=false;
    bool reDraw=true;
    int xOff =0;
    int yOff =0;
    int count = 0;
    int FPS = 5;
    int x=10, y=10;
    int moveSpeed = 5;


    display = al_create_display(ScreenWidth,ScreenHeight);

    if(!display)
        al_show_native_message_box(NULL,NULL,NULL, "Could not create Allegro Window", NULL,NULL);


    al_set_window_title(display,"Outfall-RPG");

    al_install_keyboard();
    ALLEGRO_EVENT_QUEUE *event_queue = NULL;

    event_queue = al_create_event_queue();
    timer = al_create_timer(1.0 / FPS);             // 1.0 = Sekunden; / FPS = Frames per Second

    al_register_event_source(event_queue, al_get_keyboard_event_source());
    al_register_event_source(event_queue, al_get_display_event_source(display));
    al_register_event_source(event_queue, al_get_timer_event_source(timer));

    al_start_timer(timer);



    while(!done)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(event_queue, &ev);

        map map;
        map.Init();
        map.LoadMap("map1.txt");


        if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
        {
            switch(ev.keyboard.keycode)
            {
                case ALLEGRO_KEY_ESCAPE:
                    done=true;
                    break;
                case ALLEGRO_KEY_LEFT:
                    keys[LEFT] = true;
                    break;
                case ALLEGRO_KEY_RIGHT:
                    keys[RIGHT] = true;
                    break;
                case ALLEGRO_KEY_UP:
                    keys[UP] = true;
                    break;
                case ALLEGRO_KEY_DOWN:
                    keys[DOWN] = true;
                    break;
            }
        }
        else if(ev.type == ALLEGRO_EVENT_KEY_UP)
        {
            switch(ev.keyboard.keycode)
            {
                case ALLEGRO_KEY_ESCAPE:
                    done=true;
                    break;
                case ALLEGRO_KEY_LEFT:
                    keys[LEFT] = false;
                    break;
                case ALLEGRO_KEY_RIGHT:
                    keys[RIGHT] = false;
                    break;
                case ALLEGRO_KEY_UP:
                    keys[UP] = false;
                    break;
                case ALLEGRO_KEY_DOWN:
                    keys[DOWN] = false;
                    break;
                }
        }
        else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
        {
            break;
        }
        else if(ev.type == ALLEGRO_EVENT_TIMER)
        {
            xOff -= keys[RIGHT] * 3;
            xOff += keys[LEFT] * 3;
            yOff -= keys[DOWN] * 3;
            yOff += keys[UP] * 3;

            reDraw=true;
        }
        if(reDraw && al_is_event_queue_empty(event_queue))
        {
            map.Draw(xOff, yOff);
            //al_set_target_bitmap(al_get_backbuffer(display));
            al_flip_display();
            al_clear_to_color(al_map_rgb(0,0,0));



            reDraw=false;

        }
    }

    al_destroy_event_queue(event_queue);
    al_destroy_timer(timer);
    al_destroy_display(display);
    return 0;
}

map.h

#include <fstream>
#include <string>
#include <algorithm>
#include <iostream>
#include "global.h"
#include<allegro5\allegro.h>
#include<allegro5\allegro_native_dialog.h>
#include<allegro5\allegro_primitives.h>

using namespace std;

class map
{
    public:
        map();
        ~map();

        void Init();
        void Update();
        ALLEGRO_BITMAP  *buffer;

        void LoadMap(const char *filename);
        void Draw(int &xOff, int &yOff);

    private:
        int loadCounterX, loadCounterY;
        int mapSizeX, mapSizeY;
        int MapFile[200][200];
        int BlockSize;

        ALLEGRO_BITMAP  *bgSheet;



        int mapColumns;
        int mapSize;
        int y;
        int sheetSize;

};

map.cpp:

#include "map.h"

map::map()
{
    mapSizeX = 101;
    mapSizeY = 101;
    y=0;
    sheetSize = 13;
}

map::~map()
{
}

void map::Init()
{
    loadCounterX = loadCounterY = 0;
    map::LoadMap("maptest.txt");
    BlockSize = 32;
    int MapFile[100][100];
    mapColumns = 100;
    mapSize = 1000;

}

void map::Update()
{
}

void map::Draw(int &x, int &q)
{
    int xOff = x;
    int yOff = q;
    bgSheet = al_load_bitmap("bilder/testas1.png");
    buffer = al_create_bitmap(800,600);
    //al_set_target_bitmap(buffer);


        for (int i=0; i<mapSizeX; i++)
        {
            for (int j=0; j<mapSizeY; j++)
            {
                y=0;

                while(MapFile[i][j] > sheetSize)
                {
                    MapFile[i][j] = MapFile[i][j] - sheetSize;  
                    y++;
                }

                // al_draw_bitmap_region(bgSheet, BlockSize*(MapFile[i][j]-1),BlockSize*y, BlockSize, BlockSize, xOff + BlockSize * (i%mapColumns), yOff + BlockSize * (j%mapColumns),0);
                //al_set_target_bitmap(buffer);
                al_draw_bitmap_region(bgSheet, BlockSize*(MapFile[i][j]-1),BlockSize*y, BlockSize, BlockSize, xOff + (BlockSize *i), yOff + (BlockSize * j),0);


                //al_set_target_backbuffer(display);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                // Generell gucken, wie ich schneller BITMAPS abbilden kann!
                //ALLEGRO_BITMAP *al_get_backbuffer(ALLEGRO_DISPLAY *display)
                //  al_set_target_bitmap(display);

                // Nur abgebildeter Bereich + Puffer blitten (20x20?)

            }
        }
}

void map::LoadMap(const char *filename)
{

    ifstream openfile(filename);
    if (openfile.is_open())
    {
        string line;
        getline(openfile, line);
        line.erase(remove(line.begin(),line.end(),' '), line.end());
        mapSizeX = 100;

        openfile.seekg(0,ios::beg);
        //openfile >> mapSizeX >> mapSizeY;

        while(!openfile.eof())
        {
            openfile >> MapFile[loadCounterX][loadCounterY];
            loadCounterX ++;

            if (loadCounterX >= mapSizeX)
            {
                loadCounterX = 0;
                loadCounterY++;
            }
        }

        mapSizeY = loadCounterY;
    }   //File is Opend

    else
    {
        //al_show_native_message_box(NULL,NULL,NULL, "Could not load Map", NULL,NULL);
    }
}

the tiles im using:

https://i.sstatic.net/k4DbZ.png


Solution

  • These lines of map::Draw are suspicious:

    bgSheet = al_load_bitmap("bilder/testas1.png");
    buffer = al_create_bitmap(800,600);
    

    map::Draw re-loads your bitmap every time you call it. Not only does this put needless load on your draw loop, but you are leaking the loaded bitmap every time.

    Try loading bgSheet just once in map::Init and using that same bitmap for every draw loop.

    You also allocate and subsequently leak a new buffer for every draw call. It appears that you aren't using the buffer, so I would remove that al_create_bitmap call entirely. If your intent was to double-buffer, that generally isn't needed in allegro5.

    Also, it looks like map::Init is called in your game loop, which means you are repeatedly loading the map and probably spending a lot of time waiting on I/O. Call map::Init once before your game loop begins.