用Qt开发游戏时一些问题的解决方法(一)

来源:互联网 发布:什么是大数据概念 编辑:程序博客网 时间:2024/06/06 03:42

 本文转自http://hi.baidu.com/sunny_xinxue/blog/item/b22e9aefed2f94d9b21cb163.html

谢谢作者分享.

Qt是一个不错的库。因此在一些场合下,可以基于Qt搭建程序和游戏框架。

下面谈下Qt作为游戏框架所遇到的问题及解决方法

(一)按键

可重载Widget中的keyPressEvent、keyReleaseEvent、mousePressEvent、mouseReleaseEvent、mouseMoveEvent函数处理

但keyPressEvent有一个问题。在Windows下(别的环境我不知道……),按住一个键时,会先响应一次,停顿一会,然后才开始不断响应。在游戏中这种特性的表现是 人物先走一步,停一下,然后继续不断地走。

这个特性非常影响游戏体验,因此通常的解决方法是:press时,设置某个flag为true,release时,设flag为false,然后在游戏渲染循环中根据flag的值决定人物的行动(即通过忙等待方式而不是中断方式)

但Qt的键盘函数仍然有一个问题,它不是“人按下按键才触发keyPressEvent,弹起按键才触发keyReleaseEvent”,而是“输出按键消息前触发keyPressEvent,输出后触发keyReleaseEvent”。表现为按住一个键时,不断地press、release、press、release、press、release……

好在Qt提供了另一个功能,键盘事件类QKeyEvent中提供autorepeat判断,即按住按键时触发的那些键盘事件属于autorepeat类型,因此可据此排除中间的那些press、release

但Qt的键盘事件依然有一个非常囧的现象(我不清楚为啥会这样),按住一个键时:

1. 触发keyPressEvent,isAutoRepeat()返回false

2. 没有触发keyReleaseEvent,停顿一会

3. 触发keyPressEvent,isAutoRepeat()返回true

4. 触发keyReleaseEvent

5. 若没松开按键,isAutoRepeat()返回true,返回3;松开按键,isAutoRepeat()返回false

所以有时需要设置一个flag避免第二步造成的影响

最终代码如下:

keyPress

view plaincopy to clipboardprint?
void BattleGameManager::keyPressEvent(QKeyEvent* evt)  
{  
    switch(evt->key()){  
        case Qt::Key_W:   
            if(!evt->isAutoRepeat()){                  
                if(mPressFlag_W){  
                    //按键按下时发生的事件  
                }  
                --mPressFlag_W; //改变flag  
            }  
            break;
void BattleGameManager::keyPressEvent(QKeyEvent* evt)
{
switch(evt->key()){
   case Qt::Key_W:
    if(!evt->isAutoRepeat()){    
     if(mPressFlag_W){
      //按键按下时发生的事件
     }
     --mPressFlag_W; //改变flag
    }
    break;

keyRelease

view plaincopy to clipboardprint?
void keyReleaseEvent(QKeyEvent* evt)  
{  
    switch(evt->key()){  
        case Qt::Key_W:   
            if(!mPressFlag_W||!evt->isAutoRepeat()){  
                //松按键时发生的事件  
                mPressFlag_W=1;  
            }  
            break;  
        default: break;  
    }  
    QWidget::keyReleaseEvent(evt);  
}
void keyReleaseEvent(QKeyEvent* evt)
{
switch(evt->key()){
   case Qt::Key_W:
    if(!mPressFlag_W||!evt->isAutoRepeat()){
     //松按键时发生的事件
     mPressFlag_W=1;
    }
    break;
   default: break;
}
QWidget::keyReleaseEvent(evt);
}

To be continued.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wsrlyk/archive/2010/05/28/5631573.aspx