4

I'm building the "Tanks" game where I'm using Key event to run my tank on map. Actually I can only use one key at the time but I need to have ability to f.e. go up and left simultaneously.

Here's my code for single key events:

switch(event->key())
{
case Qt::Key_Up:
    if(!ui->widget->playerList[playerID]->canMove(0.3, 20, 20, -20, -20, 1.5)) return;
    ui->widget->playerList[playerID]->move(0.3);
    ui->widget->updateGL();
    break;
case Qt::Key_Down:
    if(!ui->widget->playerList[playerID]->canMove(-0.2, 20, 20, -20, -20, 1.5)) return;
    ui->widget->playerList[playerID]->move(-0.2);
    ui->widget->updateGL();
    break;
case Qt::Key_Right:
    ui->widget->playerList[playerID]->rotate(10);
    ui->widget->updateGL();
    break;
case Qt::Key_Left:
    ui->widget->playerList[playerID]->rotate(-10);
    ui->widget->updateGL();
    break;
case Qt::Key_Q:
    ui->widget->playerList[playerID]->rotateCannon(10);
    ui->widget->updateGL();
    break;
case Qt::Key_E:
    ui->widget->playerList[playerID]->rotateCannon(-10);
    ui->widget->updateGL();
    break;
default:
    QMainWindow::keyPressEvent(event);
    break;
} 
Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35
Tomasz Kasperek
  • 1,147
  • 3
  • 13
  • 35

2 Answers2

6

You can add a pressed key to the set of pressed keys and remove from this set when the key is released. So you can add the pressed key to a QSet which is a class member :

QSet<int> pressedKeys;

You can catch the key events in an event filter :

bool MyWidget::eventFilter(QObject * obj, QEvent * event)
{

    if(event->type()==QEvent::KeyPress) {

        pressedKeys += ((QKeyEvent*)event)->key();

        f( pressedKeys.contains(Qt::Key_Up) && pressedKeys.contains(Qt::Key_Left) )
        {
            // up and left is pressed
        }

    }
    else if(event->type()==QEvent::KeyRelease)
    {

        pressedKeys -= ((QKeyEvent*)event)->key();
    }


    return false;
}

Don't forget to install the event filter in the constructor:

this->installEventFilter(this);
Nejat
  • 31,784
  • 12
  • 106
  • 138
  • It kind of works, but: When I move my tank with both up arrow and left arrow key pressed it makes a circle, which is fine. But I also want to do something like when I'm going to release one of those buttons it will continue for example rotating when I'm gonna release up arrow key and hold only left arrow key, without lag. – Tomasz Kasperek May 23 '14 at 14:25
2

Maybe you could consider looking into the masks? Let's say you have directions, define a mask that has four bits:

0 0 0 0

U D L R

And each time you just need to check what keys are pressed. By AND with the masks:

1000 - Up

0111 - Down

0010 - Left

0001 - Right

Juto
  • 1,246
  • 1
  • 13
  • 24