Аллегро проблема с частотой кадров

Так что у меня были некоторые проблемы с Allegro в последнее время. Я понятия не имею, что вызывает это, но я постараюсь подробно описать проблему ниже, насколько это возможно.

В моей основной функции у меня есть что-то вроде этого:

int main()
{
    Game *game = new Game();
    game->init(800, 600, 60); //width, height, framerate

    PlayState *playState = new PlayState(); //extends abstract class GameState
    game->setDefaultState(playState);

    game->startGame();

    gMemoryTracker.reportAllocations(cout);
    system("pause");
    return 0;
}

Это работает нормально, и печать прошедшего времени в конце каждого кадра показывает около 16,7 мс на кадр. Однако, поскольку я хотел бы, чтобы класс Game в конечном итоге действовал как полноценный менеджер GameState (в настоящее время он поддерживает только один GameState), я хотел бы, чтобы функция инициализации класса Game вызывала собственную индивидуальную функцию инициализации каждого GameState. Очевидно, это означало бы регистрацию каждого GameState перед вызовом функции инициализации игры, поэтому я изменил основную функцию, чтобы она выглядела следующим образом:

int main()
{
    Game *game = new Game();
    //this is where the call to init used to be

    PlayState *playState = new PlayState();
    game->setDefaultState(playState);

    game->init(800, 600, 60); //now this is called after we create a GameState and set it as default

    game->startGame();

    gMemoryTracker.reportAllocations(cout);
    system("pause");
    return 0;
}

Проблема в том, что теперь для рендеринга каждого кадра требуется около 1100 мс, хотя класс Game сообщает, что частота кадров по-прежнему установлена ​​на 60 кадров в секунду. Пытаясь решить эту проблему, я сделал последнее изменение в main:

int main()
{
    Game *game = new Game();   

    PlayState *playState = new PlayState();
    game->init(800, 600, 60); //now init is being called after we create a new GameState, but before we set it as default
    game->setDefaultState(playState);

    game->startGame();

    gMemoryTracker.reportAllocations(cout);
    system("pause");
    return 0;
}

Но это приводит к той же проблеме, что и раньше: рендеринг каждого кадра занимает около 1100 мс. Кажется, что эта проблема возникает только тогда, когда я вызываю init после создания нового GameState, поэтому я посмотрел на конструктор класса PlayState и функцию init класса Game, чтобы увидеть, смогу ли я найти что-то, что вызовет такое поведение, но я до сих пор не смогли найти причину. Вы можете найти две вышеупомянутые функции ниже:

bool Game::init(int width, int height, float frameRate)
{
    mFrameRate = frameRate;
    bool result = mpGraphics->init(width, height); //initialize the graphics system

    //this calls the init function for the default GameState. commented-out for debugging purposes
    //result = result && mpDefaultState->init();

    return result; //were all inits successful?
}



PlayState::PlayState() : GameState("play_state")
{
    //create required graphics buffers and fonts
    bgBuffer = new GraphicsBuffer(DISPLAY_SIZE.getX(), DISPLAY_SIZE.getY());
    woodsBuffer = new GraphicsBuffer(ASSET_PATH + "Woods.png");
    smurfBuffer = new GraphicsBuffer(ASSET_PATH + "smurf_sprites.png");
    font = new Font(ASSET_PATH + "cour.ttf", 12);

    smurfAnimation = new Animation(60, true); //create new animation for smurf walk cycle. args are animation framerate (must be <= game framerate) and loop animation

    //load sprites from spritesheet
    for (int y = 0; y < (int)SPRITE_SHEET_SIZE.getY() / (int)SPRITE_SIZE.getY(); y++)
    {
        for (int x = 0; x < (int)SPRITE_SHEET_SIZE.getX() / (int)SPRITE_SIZE.getX(); x++)
        {
            //there was already a class named Rectangle, so i had to get creative
            UnequalSquare uSquare(x * (int)SPRITE_SIZE.getX(), y * (int)SPRITE_SIZE.getY(), (int)SPRITE_SIZE.getX(), (int)SPRITE_SIZE.getY());
            smurfAnimation->addSprite(Sprite(*smurfBuffer, uSquare));
        }
    }
}

Я также заметил, что игра работает с правильной частотой кадров, если я закомментирую все вызовы рендеринга в функции рендеринга PlayState, но, очевидно, это нежизнеспособное решение. Я опубликую функцию рендеринга ниже. На данный момент это не очень эффективно (создание новых объектов спрайтов в каждом кадре), но это не объясняет, почему он отлично работает, если Game.init() вызывается перед созданием экземпляра PlayState.

void PlayState::render(GraphicsSystem* graphics, const Timer& frameTimer)
{
    // Create background
    Sprite bgSprite(*bgBuffer);
    graphics->fill(*bgBuffer, Color(255, 0, 0));

    // Create image
    Sprite woodsSprite(*woodsBuffer);
    Vector2D woodsLocation((DISPLAY_SIZE.getX() - (woodsSprite.getWidth() * WOODS_SCALE)) / 2.0, (DISPLAY_SIZE.getY() - (woodsSprite.getHeight() * WOODS_SCALE)) / 2.0);

    // Draw Text
    int fontWidth = font->getTextWidth(TEXT_STRING);
    int fontHeight = font->getFontHeight();

    for (int i = 0; i <= DISPLAY_SIZE.getY() / fontHeight; i++)
    {
        for (int j = 0; j <= DISPLAY_SIZE.getX() / fontWidth; j++)
        {
            graphics->drawText(*bgBuffer, Vector2D(j * fontWidth, i * fontHeight), TEXT_STRING, *font, Color());
        }
    }

    //update the animation
    smurfAnimation->update();

    // Draw sprites to backbuffer
    graphics->drawSpriteToBackbuffer(gZeroVector2D, bgSprite);
    graphics->drawSpriteToBackbuffer(woodsLocation, woodsSprite, WOODS_SCALE);
    graphics->drawSpriteToBackbuffer(gZeroVector2D, smurfAnimation->getCurrentSprite());
}

Может ли кто-нибудь увидеть причину, по которой я могу столкнуться с этой проблемой? Я был в этом в течение нескольких часов, и я не могу понять это для жизни меня.


person android927    schedule 22.02.2015    source источник


Ответы (1)


Я нашел проблему. Из документации Allegro 5:

Если вы не установите флаг ALLEGRO_MEMORY_BITMAP, растровое изображение создается для текущего дисплея. Перенос на другой дисплей может быть медленным.

Я пытался создать растровые изображения до того, как создал отображение, что привело к низкой производительности. Установка флага ALLEGRO_MEMORY_BITMAP значительно увеличивает частоту кадров, но по-прежнему занимает около 100-200 мс на кадр. Я полагаю, что это просто слабость Allegro, которую мне нужно будет принимать во внимание с этого момента.

Источник: https://www.allegro.cc/manual/5/al_create_bitmap

person android927    schedule 22.02.2015
comment
Возможное ускорение, которое вы можете использовать, состоит в том, чтобы сделать отображение вне вашего класса менеджера игры, например, внутри основного, и передать указатель на него вашему классу на случай, если он вам понадобится внутри, таким образом, отображение может начаться до растрового изображения. загрузки, а затем использовать растровые изображения видео вместо растровых изображений памяти. Конечно, я не знаю вашей архитектуры для игры, так что это может быть невозможным вариантом. - person rlam12; 29.03.2015