[Kde-games-devel] keyboard delay on keyPressEvent

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Wed Feb 25 21:54:55 CET 2004


> If you say kasteroids is the behaviour you want you might have a look at
> this
>
> void KAstTopLevel::focusInEvent( QFocusEvent *e )
> {
> // bla bla
>     XAutoRepeatOff( qt_xdisplay() );
>     KMainWindow::focusInEvent(e);
> }

[...]

> This sets autorepeat off the the windows has the focus and sets in on when
> it loses it and when the window is destroyed. I could not find
> qt_xdisplay() in assistant documentation but looking for it in the qt src
> it says

Actually, this is not even necessary, and it's not the thing you're looking 
fore. Rather, the whole point is, to not act directly on the keyboard events, 
but rather to use your own timing. I'm using essentially the same method in 
taxipilot, so I'll outline the basic steps (quoting the relevant lines from 
kasteroids):

First, make sure you get notified of all keypresses and keyreleases:

KAstTopLevel::KAstTopLevel()
{
// snip
	installEventFilter(this);
}

// override for virtual protected function:
bool KAstTopLevel::eventFilter( QObject* /* object */, QEvent *event )
{
        QKeyEvent *e = dynamic_cast<QKeyEvent*>(event);
        if (event->type() == QEvent::AccelOverride)
        {
                if (processKeyPress(e)) return true;
                else return false;
        }
        else if (event->type() == QEvent::KeyRelease)
        {
                if (processKeyRelease(e)) return true;
                else return false;
        }
        return false;
}

bool KAstTopLevel::processKeyPress( QKeyEvent *event )
{
// snip
/* the above lines determined that e.g. the key for rotating left has just 
been pressed (or is auto-repeating) */ 
            view->rotateLeft( true );
// read: view->rotateL = true;
}

bool KAstTopLevel::processKeyRelease( QKeyEvent *event )
{
// snip
/* the above lines determined that e.g. the key for rotating left has just 
been released */ 
            view->rotateLeft( false );
// read: view->rotateL = false;
}

Now, view->rotateLeft ( true ) does not really rotate the ship, but merely 
sets a variable (rotateL) to true. Since we catch both keypresses and 
-releases in the eventfilter, this way that variable will always reflect the 
current state of the key (pressed or not pressed), regardless of autorepeat.
Now, all that's left to do is start a timer in whatever rate we like and act 
according to the keys pressed. Hence the last parts in the chain:

void KAsteroidsView::timerEvent( QTimerEvent * )
{
// snip
    processShip();
}

void KAsteroidsView::processShip()
{
// snip
        if ( rotateL )
        {
		// do the acutal rotation
        }
}

Of course, this is a bit more complicated than just rotating the ship whenever 
you get a keyPressed-signal (autorepeat or press). But it's not as 
complicated as it may look at first. Since you likely have some kind of timer 
anyway for doing collision detection and the like, it's actually just a few 
additional lines. It's even less lines, if you don't split it into quite as 
many separate functions.

Hope this helps.
Thomas



More information about the kde-games-devel mailing list