用Qt開發遊戲時一些問題的解決方法(一)

 本文轉自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


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章