【问题标题】:C++ Setting a frame rate in a game like TetrisC++ 在俄罗斯方块等游戏中设置帧速率
【发布时间】:2014-11-12 06:16:12
【问题描述】:

所以这个问题比一些问题要抽象一些。假设我有一个我只想每秒渲染一次的游戏,例如俄罗斯方块克隆。我只想每秒处理一个输入,然后相应地渲染新帧。俄罗斯方块是一个基于网格的游戏,所以我不能只将游戏块移动一定量,乘以人们通常用于帧速率示例的timeDelta 浮点数。如何在基于网格的游戏中每秒只渲染一帧?这是我到目前为止的代码,但它是错误的:

void Engine::Go(){
    while(window.isOpen()){
        if(timeElapsed >= 1000){
            timeElapsed = clock.restart().asMilliseconds();;
            ProcessInput();
        }
        UpdateCPU();
        Render();
        timeElapsed = clock.getElapsedTime().asMilliseconds();
        time += timeElapsed;
    }
}

void Engine::ProcessInput(){
    while(window.pollEvent(event)){
        if(event.type == (sf::Event::Closed))
            window.close();
    }
    //process movement detection of piece
    int temp = level.GetGamePieces().size();
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(-10, 0);
        std::cout << "left";
        moved = true;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(10,0);
        std::cout << "right";
        moved = true;
    }
    else{
        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(0,10);
        std::cout << "down";
        moved = true;
    }
}

我只想一次移动一个格子,每秒一次,但我就是不知道该怎么做。

编辑:这是渲染帧的代码

void Engine::Render(){
    window.clear();
    //draw wall tiles
    for(int i = 0; i < 160; i++){
        if(i < 60){
            level.GetWallTile().setPosition(0, i * 10);
            window.draw(level.GetWallTile());
        }
        if(i >= 60 && i < 100){
            level.GetWallTile().setPosition((i - 60) * 10, 590);
            window.draw(level.GetWallTile());
        }
        if(i >= 100){
            level.GetWallTile().setPosition(390, (i - 100) * 10);
            window.draw(level.GetWallTile());
        }
    }

    //draw BG tiles
    for(int i = 1; i < 39; i++){
        for(int j = 0; j < 59; j++){
            level.GetBGTile().setPosition(i * 10, j * 10);
            window.draw(level.GetBGTile());
        }
    }

    for(int i = 0; i < level.GetGamePieces().size(); i++){
        window.draw(level.GetGamePieces()[i].GetPieceSprite());
    }

    window.display();
}

【问题讨论】:

  • void sf::Window::setFramerateLimit(int limit)?
  • 您绝对不想每秒只处理一次用户输入。游戏会感觉非常糟糕。您需要尽快处理输入,或者每秒至少处理 30 次。
  • @StilesCrisis 好吧,这听起来比我的计划要好,但是我如何每秒只渲染一次呢?此外,仅有的三个输入每秒只会生效一次。例如,如果在一秒钟内按了三次右箭头键,我不希望在下一次更新之前让棋子向右移动三个空格。
  • 将您的更新速率设置为响应速度快——大约每秒 30 次应该没问题。然后使用计数器来决定是否需要在更新期间移动碎片。

标签: c++ frame sfml rate


【解决方案1】:

您没有考虑到用户可能希望在形状移动之间移动一个形状。

您应该允许用户随时向左、向右和向下移动形状,但是 在经过的时间结束之前不要强制向下移动。

When I made a block-based game, here's what I did

void updateSeconds( double deltaTime ) {
// If timer until shape falls runs out, move the shape down.
    timeUntilShapeDrop -= deltaTime;
    if ( timeUntilShapeDrop > 0 || currentFallingShape->isAnimating() ) {
        return;
    }

    // If ( shape collides with map when moved down )
    currentFallingShape->move(-1,0);
    if ( currentFallingShape->isCollisionWithMap ( * map ) ) {
        currentFallingShape->move(1,0);

        // Lock shape in place on the map
        currentFallingShape->setBlocksOnMap( * map );
        lastUpdateLinesCleared = clearFullLines();
    }
    timeUntilShapeDrop = calculateShapeDropTimeInterval();

如果您对其中一种方法感兴趣,我还包括渐变形状动画。我在逻辑地图之上构建了一个图形游戏地图,并使用逻辑地图开始图形插值。我打破了我正在使用的图形库,但逻辑代码仍然可以参考或使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 1970-01-01
    相关资源
    最近更新 更多