用C++和SFML寫遊戲-事件的處理(4)

處理好來自用戶的事件是一個很重要的話題。php

首先咱們來認識一下什麼是事件函數

通常來講,事件是在某些狀況下被觸發的對象。它們依賴於操做系統,可是 SFML 爲咱們提供了一個很好的對象來處理事件,它是獨立於操做系統的方式。sf::Event 類,這個類包含了各類事件。學習

建議閱讀 SFML 官方文檔去好好了解 SFML 事件的類型,地址是https://www.sfml-dev.org/tutorials/2.5/window-events.php。 注意 sf::Event 是一個聯合體(union),使用的時候要恰當的選擇咱們須要的事件類型。編碼

邏輯上,咱們能夠將事件分紅四種類型:spa

  • 窗口
  • 鍵盤
  • 鼠標
  • 手柄

1、窗口事件

類型 相關成員 描述
Event::Closed None 當操做系統檢測單用戶想要關閉窗口時觸發
Event::Resized Event::size 表示新窗口的大小 當操做系統檢測單用戶想要改變窗口大小時觸發,或者調用Window::setSize()
Event::LostFocus Event::GainedFocus None 當窗口失去/獲得焦點時觸發,失去焦點的窗口不會收到鍵盤事件

2、鍵盤事件

類型 相關成員 描述
Event::KeyPressed Event::KeyReleased Event::key 表示的事當前按住/鬆開的按鍵 在獲得焦點的窗口中,當一個按鈕被按下或者鬆開的時候觸發
Event::TextEntered Event::text 表示的是一個字符的UTF-32 unicode 任什麼時候候一個字符輸入的時候觸發

3、鼠標事件

類型 相關成員 描述
Event::MouseMoved Event::mouseMove 表示鼠標新位置 當鼠標在窗口內移動時觸發
Event::MouseButtonPressed Event::MouseButtonReleased Event::mouseButton 表示的是按下/鬆開的鼠標按鈕以及它的位置 當鼠標上的按鈕按下/鬆開的時候觸發。目前支持5種類型的按鈕:左、中、右、額外的按鈕1和按鈕2
Event::MouseWheelMoved Event::mouseWheel 表示的是滾輪以及鼠標位置 當鼠標上的滾輪滾動時觸發

4、手柄事件

類型 相關成員 描述
Event::JoystickConnected Event::JoystickDisconnected Event::joystickConnect 表示的是手柄鏈接/斷開鏈接時的ID 當手柄鏈接或者斷開鏈接時觸發
Event::JoystickButtonPressed Event::JoystickButtonReleased Event::joystickButton 表示的是手柄上按鈕按下的數量以及手柄ID 當手柄上的按鈕按下時觸發,SFML爲咱們提供了最多8個手柄,每一個手柄32個按鈕的支持
Event::JoystickMoved Event::joystickMove 表示的是移動操縱桿的軸,操縱桿軸的位置以及手柄ID 移動操縱桿的軸時會觸發此操做

對於窗口事件來講,咱們一般用 bool Window::pollEvent(sf::Event& event) 函數,若是有事件將要被使用的話,函數會返回 trueevent參數會對應某個具體事件。==須要注意的是,同一時間下可能會有多個事件須要被處理,所以咱們須要確保捕獲到每個事件。==代碼以下:操作系統

while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        
    }
    
    // 刷新幀
    // 繪製幀
}
複製代碼

運行上面這份代碼以後,咱們能夠作出移動窗口,改變窗口大小或者是最小化窗口這些操做,可是有一個問題,那就是咱們沒法關閉窗口。當咱們點擊窗口的關閉按鈕時,SFML 不會去關閉窗口,這一操做須要咱們去實現。code


5、 事件的使用

經過 Window::pollEvent() 捕獲事件以後,咱們能夠經過 Event::type 檢查事件類型。事件類型是 Event::EventTyp,它是 Event 類中的一個枚舉類型。使用方法以下對象

sf::Event event;
while (window.pollEvent(event)) {
    if (event.type == sf::Event::EventType::Closed) {
        window.close();
    }
}
複製代碼

調用 Window::close() 能夠關閉窗口。事件

若是咱們想要使用更多的事件,咱們的可使用 switch 語法。以下:unicode

sf::Event event;
while (window.pollEvent(event)) {
    switch (event.type) {
        case sf::Event::EventType::Closed:
            window.close();
            break;
        case sf::Event::EventType::KeyPressed:
            // 改變窗口標題當空格鍵按下的時候
            if (event.key.code == sf::Keyboard::Key::Space)
                window.setTitle("Space Pressed");
            break;
        case sf::Event::EventType::KeyReleased:
            // 再次改變窗口標題當空格鍵鬆開的時候
            if (event.key.code == sf::Keyboard::Key::Space)
                window.setTitle("Space Released");
            // 當 Esc 鍵鬆開的時候關閉窗口
            else if (event.key.code == sf::Keyboard::Key::Escape)
                window.close();
            break;
        default:
            break;
    }
}
複製代碼

上面這份代碼的意思很容易理解,經過空格鍵能夠改變窗口的標題,鬆開 Esc 鍵時關閉窗口。注意到 Event::key 包含了 code 成員,它是 Keyboard::Key 類型中的一個枚舉類型。用上面這種方法能夠處理其餘事件類型。

然而,Event::EventType::TextEntered的使用有點意思。按鍵被按下/鬆開的時候能夠被檢測到且可使用一種相對簡單的方式去處理。可是當鍵入一些特殊字符的時候,事情變得有點複雜起來。例如,輸入 ! 號的時候在大多數鍵盤中是使用 shift+1的。幸虧 SFML 爲咱們提供了一個簡單的方式去處理,僅當按下表示字符的組合鍵時纔會發生事件,這意味着按下一個鍵(例如 shift)時不會觸發事件。

下面這個例子使用了 TextEntered 事件組合了一個字符串,而後按下 Enter 鍵時這個字符串會顯示在窗口標題中。

sf::String buffer;
while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::EventType::Closed:
	            window.close();
    	        break;
            case sf::Event::EventType::TextEntered:
                buffer += event.text.unicode;
                break;
            case sf::Event::EventType::KeyReleased:
                if (event.key.code == sf::Keyboard::Key::Return) {
                    window.setTitle(buffer);
                    buffer.clear();
                }
                break;
            default:
                break;
        }
    }
}
複製代碼

這裏使用 sf::String 類型可以避免不一樣語言之間的字符編碼轉換。


這一節簡單介紹了 SFML 中的事件處理,下一節將會學習圖像以及精靈(sprite)的簡單使用。😃

相關文章
相關標籤/搜索