2012-07-12 81 views
0

我想爲我的項目製作第一人稱射擊風格的相機。如果我向前或向後移動,向左或向右掃動,或向對角線移動,一切看起來都很順利......問題是,當我在移動時用鼠標環顧四周,動作變得非常緊張。當我在同一時間用鼠標掃射和轉動時,這是最突出的。OpenGL3 SFML 2.0rc FPS風格的相機 - 搖搖欲墜的鼠標移動

我確信我的問題與此類似:http://en.sfml-dev.org/forums/index.php?topic=4833.msg31550#msg31550,但是我使用的是Gentoo Linux,而不是OSX。

雖然這不是SFML的錯,但我做錯了,所以我想對我的事件處理代碼做一些反饋,看看是否有更好的方法來獲得平滑的鼠標移動。

如果您不想通讀我發佈的鏈接,我認爲發生的事情就是當我將鼠標位置設置回屏​​幕中心時,鼠標移動速度正在丟失每一幀,這會在屏幕上產生一個快速可見的混亂。這是我的理論,因爲我已經嘗試過改變其他東西三天了,而我所做的一切都沒有讓它變得不那麼生澀。所以我想知道是否有人有更好的方法來處理鼠標移動,或者你是否認爲問題在別處。

一個重要的提示是我已經啓用了vsync,這使得很多其他抖動和撕裂消失,我嘗試使用像sf :: Window :: setFramerateLimit(60)這樣的硬幀率限制,但是這並沒有幫助在所有。

這裏是事件處理程序(使用SFML 2.0實時接口的事件循環,而不是),你也許可以忽略與跳躍部分:

void Test_World::handle_events(float& time) 
{ 
    // camera stuff 
    _mouse_x_pos = sf::Mouse::getPosition(*_window).x; 
    _mouse_y_pos = sf::Mouse::getPosition(*_window).y; 

    std::cout << "mouse x: " << _mouse_x_pos << std::endl; 
    std::cout << "mouse y: " << _mouse_y_pos << std::endl; 

    _horizontal_angle += time * _mouse_speed * float(_resolution_width/2 - _mouse_x_pos); 
    _vertical_angle += time * _mouse_speed * float(_resolution_height/2 - _mouse_y_pos); 

    // clamp rotation angle between 0 - 2*PI 
    if (_horizontal_angle > 3.14f*2) _horizontal_angle = 0; 
    if (_horizontal_angle < 0) _horizontal_angle = 3.14f*2; 

    // clamp camera up/down values so we can't go upside down 
    if (_vertical_angle >= 3.14f/2.0f) _vertical_angle = 3.14f/2.0f; 
    if (_vertical_angle <= -3.14f/2.0f) _vertical_angle = -3.14f/2.0f; 

    std::cout << "horiz angle: " << _horizontal_angle << std::endl; 
    std::cout << "vert angle: " << _vertical_angle << std::endl; 

    _direction = glm::vec3(cos(_vertical_angle) * sin(_horizontal_angle), 
          sin(_vertical_angle), 
          cos(_vertical_angle) * cos(_horizontal_angle)); 

    _right = glm::vec3(sin(_horizontal_angle - 3.14f/2.0f), 
         0, 
         cos(_horizontal_angle - 3.14f/2.0f)); 

    _up = glm::cross(_right, _direction); 

    // keyboard: left, right, up, down 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A)) 
    { 
     if (_jumping) 
     { 
      _position -= _right * time * _speed * ((_jump_speed/2) + 0.1f); 
     } 
     else 
     { 
      _position -= _right * time * _speed; 
     } 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D)) 
    { 
     if (_jumping) 
     { 
      _position += _right * time * _speed * ((_jump_speed/2) + 0.1f); 
     } 
     else 
     { 
      _position += _right * time * _speed; 
     } 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::W)) 
    { 
     glm::vec3 old_direction(_direction); 
     _direction.y = 0; 

     if (_jumping) 
     { 
      _position += _direction * time * _speed * ((_jump_speed/2) + 0.1f); 
     } 
     else 
     { 
      _position += _direction * time * _speed; 
     } 

     _direction = old_direction; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::S)) 
    { 
     glm::vec3 old_direction(_direction); 
     _direction.y = 0; 

     if (_jumping) 
      _position -= _direction * time * _speed * ((_jump_speed/2) + 0.1f); 
     else 
      _position -= _direction * time * _speed; 

     _direction = old_direction; 
    } 

    // keyboard: jump 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) 
    { 
     // check if standing on something 
     if (_standing) 
     { 
      _standing = false; 
      _jumping = true; 
     } 
    } 

    // apply gravity if off the ground 
    if (_position.y > _main_character_height && !_jumping) 
     _position.y -= time * _speed * _global_gravity; 

    // if started jumping 
    else if (_position.y < _main_character_height + _jump_height - 3.0f && _jumping) 
    { 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) 
     { 
      _position.y += time * _speed * _jump_speed; 
     } 
     else // if stopped jumping 
     { 
      _position += _direction * time * (_speed/(_jump_hang_time*2)); 
      _jumping = false; 
     } 
    } 

    // if near the highest part of the jump 
    else if (_position.y <= _main_character_height + _jump_height && _jumping) 
    { 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) 
     { 
      _position.y += time * _speed * (_jump_speed/_jump_hang_time); 
     } 
     else // if stopped jumping 
     { 
      _position += _direction * time * (_speed/(_jump_hang_time*2)); 
      _jumping = false; 
     } 
    } 

    // if reached the highest part of the jump 
    else if (_position.y >= _main_character_height + _jump_height) 
    { 
     _position += _direction * time * (_speed/_jump_hang_time); 
     _jumping = false; 
    } 
    else if (_position.y <= _main_character_height) 
    { 
     _standing = true; 
    } 

    sf::Mouse::setPosition(_middle_of_window, *_window); 
} 

事件之後,我改變我_view_matrix像這樣:

_view_matrix = glm::lookAt(_position, _position+_direction, _up); 

於是,我重新計算我的_modelview_matrix和_modelviewprojection_matrix:

_modelview_matrix = _view_matrix * _model_matrix; 
_modelviewprojection_matrix = _projection_matrix * _modelview_matrix; 

之後我最終將矩陣發送給我的着色器並繪製場景。

對於OpenGL3,SFML 2.0和/或FPS風格的相機處理方面,我願意接受任何聖人的智慧/建議,請讓我知道它是否有助於包含更多代碼(如果您認爲問題不是這樣例如,在事件處理中)。先謝謝您的幫助!

編輯:我還沒有解決這個問題,僅供參考它看起來並不像幀率搖搖欲墜的運動過程中,在所有下降...

回答

1

如果我是你,我會隱藏鼠標使用this tutorial,然後在到達屏幕邊緣時才移動鼠標位置,將鼠標移動到相反的一側,以便它可以在該方向上不受阻礙地繼續。可能不是最好的解決方案,但我很確定它會解決您的問題。

......另一個想法是做一些記憶和推測他們在做什麼,而不是使用位置數據本身,而只是使用位置數據來指導推算(即使用物理來控制它)而不是原始數據)。

只是我的想法,希望他們幫助^^

+0

嘿馬修,謝謝你的一些指導。我已經改變了我的程序來隱藏鼠標,並且一旦它到達屏幕邊緣,它也只能重置它的位置。這確實使動作不那麼不穩定,但是在同時掃射和旋轉時仍然會發生晃動。我真的很想用正確的方式做到這一點(用適當的物理公式),但我不知道有一個好地方可以開始瞭解這一點。任何人都可以推薦一個好的網站或教科書來解釋我需要爲初學者學習的物理類型嗎?我會看看谷歌的東西,直到我得到一個建議。 – Defcronyke 2012-08-31 17:26:31

+0

我會得到「3D遊戲編程和計算機圖形學數學第3版」,除非任何人對我有更好的主意...... – Defcronyke 2012-08-31 18:04:04