[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