快板帧速率问题

Allegro framerate issue

本文关键字:问题 帧速率      更新时间:2023-10-16

所以我最近在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.7ms。然而,由于我希望Game类最终充当一个成熟的GameState管理器(目前它只支持一个GameState),我希望游戏类的init函数调用每个GameState自己的init函数。显然,这意味着在调用游戏的init函数之前注册每个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;
}

问题是,尽管Game类报告帧速率仍设置为60fps,但现在每帧的渲染时间约为1100ms。为了调试这个问题,我对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毫秒。这个问题似乎只有在创建新的GameState后调用init时才会发生,所以我查看了PlayState类的构造函数和Game类的init函数,看看是否能找到导致这种行为的原因,但我仍然无法找到原因。您可以在下面找到上述两个功能:

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渲染函数中的所有渲染调用,游戏将以正确的帧速率运行,但显然这不是一个可行的解决方案。我将在下面发布渲染函数。目前它的效率不是很高(每帧创建一个新的精灵对象),但这并不能解释为什么在创建PlayState实例之前调用Game.int()会完美工作。

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());
}

有人知道我遇到这个问题的原因吗?我已经做了几个小时了,我一辈子都想不出来。

我发现了问题。来自Allegro 5文档:

除非设置ALLEGRO_MEMORY_BITMAP标志,否则将为当前显示创建位图。对另一个显示器的Blitting可能很慢。

在创建显示之前,我试图创建位图,因此导致性能较差。设置ALLEGRO_MEMORY_BITMAP标志可以显著提高帧速率,但每帧仍需要约100ms-200ms的时间。我想这只是快板的一个弱点,从现在开始我需要考虑

来源:https://www.allegro.cc/manual/5/al_create_bitmap