C ++ Установка частоты кадров в такой игре, как Тетрис

Так что этот вопрос немного более абстрактный, чем некоторые другие. Скажем, у меня есть игра, которую я хочу визуализировать только один раз в секунду, например, клон Tetris. Я хочу обрабатывать только один ввод в секунду, а затем соответствующим образом визуализировать новый кадр. Тетрис - это игра, основанная на сетке, поэтому я не могу просто переместить игровой элемент на определенную величину, умноженную на timeDelta float, которое люди обычно используют для примеров частоты кадров. Как мне сделать рендеринг только одного кадра в секунду в игре на основе сетки? Вот какой у меня код, но он неправильный:

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

person jburn7    schedule 18.09.2014    source источник
comment
void sf :: Window :: setFramerateLimit (ограничение числа)?   -  person Lefsler    schedule 18.09.2014
comment
Вы определенно не хотите обрабатывать вводимые пользователем данные только один раз в секунду. Игра была бы ужасно сломанной. Вам необходимо обрабатывать ввод, как только он поступает, или как минимум 30 раз в секунду.   -  person StilesCrisis    schedule 18.09.2014
comment
@StilesCrisis Хорошо, это звучит лучше, чем мой план, но как мне выполнять рендеринг только раз в секунду? Кроме того, всего три входа будут действовать только один раз в секунду. Например, если нажать клавишу со стрелкой вправо три раза за одну секунду, я не хочу, чтобы кусок сдвинулся вправо на три деления до следующего обновления.   -  person jburn7    schedule 18.09.2014
comment
Установите частоту обновления так, чтобы она выглядела отзывчивой - около 30 раз в секунду должно быть нормально. Затем используйте счетчик, чтобы решить, нужно ли вам перемещать части во время этого обновления.   -  person paddy    schedule 18.09.2014


Ответы (1)


Вы не учитываете тот факт, что пользователь может захотеть переместить фигуру между движениями фигуры.

Вы должны позволить пользователю перемещать фигуру влево, вправо и вниз, когда он / она хочет, но не форсировать движение вниз до тех пор, пока не истечет истекшее время.

Вот что я сделал, когда делал блочную игру

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

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

person pyj    schedule 18.09.2014