Создание движущегося 2D-объекта в Qt OpenGL

Я пишу многопользовательскую игру "танки" в режиме deathmatch, в которой игроки могут присоединиться к серверу и управлять танком, стрелять и т. д. В данный момент я хочу сделать механизм передвижения по карте (2D). Я пробовал некоторые методы, но они не удовлетворяют.

Прямо сейчас я использую QTimer, который отлично работает с одним игроком на карте, но когда я присоединяюсь ко второму, они оба начинают отставать.

Метод keyPressEvent

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
        case Qt::Key_Up:
            keyUp = true;
            break;
        case Qt::Key_Down:
            keyDown = true;
            break;
    }
 }

keyPressEvent и keyReleaseEvent похожи, а не в событии релиза есть f.e. keyUp = false заявление.

Метод movePlayer

void MainWindow::movePlayer()
{
    if(keyUp)
        ui->widget->playerList[playerID]->move(0.2);
    else if(keyDown)
        ui->widget->playerList[playerID]->move(-0.1);
    if(keyLeft)
        ui->widget->playerList[playerID]->rotate(-5);
    else if(keyRight)
        ui->widget->playerList[playerID]->rotate(5);
    if(keyE)
        ui->widget->playerList[playerID]->rotateCannon(-3);
    else if(keyQ)
        ui->widget->playerList[playerID]->rotateCannon(3);
}

Метод onTimer (отправляет сообщение на сервер с указанием местонахождения резервуара)

void MainWindow::onTimer()
{
    movePlayer();
    QTextStream out(socket);
    out << QString::number(ui->widget->playerList[playerID]->id)
           + " " + QString::number(ui->widget->playerList[playerID]->getXPos())
           + " " + QString::number(ui->widget->playerList[playerID]->getYPos())
           + " " + QString::number(ui->widget->playerList[playerID]->getRotation()) << endl;
    ui->widget->updateGL();
}

Как я могу написать/переписать код для достижения моей цели плавной работы 2 и более резервуаров?


person Tomasz Kasperek    schedule 26.05.2014    source источник


Ответы (1)


один рендер, одно обновление

Проблема может заключаться в том, что вы работаете с игроками независимо.

Простой игровой цикл должен обрабатывать каждую часть за один раз. Вы бы предпочли иметь логический код на одном таймере, а рендеринг — на другом. Или просто используйте один таймер и делайте все сразу на каждом шаге таймера. Это должно сгладить игровой процесс.

// pseudo code
clockTick() {
  // do logic
  for (player : players)
    movePlayer(player);
  // Update graphics
  updateGL();
}

Обязательно ознакомьтесь с этой замечательной статьей об игровом цикле.

person mrVoid    schedule 26.05.2014
comment
Спасибо. Вы можете изменить возвращаемое значение функции. - person lpapp; 26.05.2014
comment
Я мог бы получить это в одиночной игре, где вся логика происходит на одном компьютере. Но я понятия не имею, как добиться этого с помощью QTcpSocket. Потому что я обновляю всех игроков в слоте infoReceived(), который срабатывает каждый раз, когда я получаю информацию с сервера. - person Tomasz Kasperek; 26.05.2014