上一篇已經使用 sdl2 顯示了一個窗口, 咱們當時的作法是讓線程休眠 10 秒看了個窗口的樣子, 如今咱們想讓這個窗口經過咱們主動觸發事件來關閉, 其餘正常狀況下一直運行.git
開始以前先建立個分支, git checkout -b events
github
讓窗口一直顯示很好辦, 在原先代碼基礎上, 經過一個死循環就能解決.正則表達式
use sdl2::pixels::Color;
fn main() {
let sdl2_context = sdl2::init().unwrap();
let video = sdl2_context.video().unwrap();
let window = video
.window("Arcade Shooter", 800, 600)
.position_centered()
.opengl()
.build()
.unwrap();
let mut canvas = window.renderer().accelerated().build().unwrap();
canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear();
canvas.present();
'running: loop {}
}
複製代碼
Rust 有一個 loop
的循環方式, 'running
能夠不用理會只是個生命週期標記. 如今這個程序所處的狀態算不上一個正常的狀態, 以後要讓程序能夠受用戶控制關閉.canvas
rust-sdl2
的事件控制方法在其 github 倉庫 examples 中有, 就這個樣子, 經過調用 sdl2_context
的 event_pump
函數獲取 sdl2 的事件集, 再在循環中遍歷經過事件集的 poll_iter
函數獲取到的輪詢迭代器ide
let mut event_pump = sdl2_context.event_pump().unwrap();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
break 'running
},
_ => {}
}
}
}
複製代碼
咱們要處理的事件是程序 Quit
事件和按了鍵盤的 escape
的事件, 如今來建立個文件, 就叫 events.rs
, 放到 main.rs
同級目錄下函數
use sdl2::EventPump;
pub struct Events {
pump: EventPump,
pub quit: bool,
pub key_escape: bool,
}
impl Events {
pub fn new(pump: EventPump) -> Self {
Self {
pump,
quit: false,
key_escape: false,
}
}
pub fn pump(&mut self) {
for event in self.pump.poll_iter() {
use sdl2::event::Event::*;
use sdl2::keyboard::Keycode::*;
match event {
Quit { .. } => self.quit = true,
KeyDown {
keycode: Some(Escape),
..
} => self.key_escape = true,
_ => {}
}
}
}
}
複製代碼
如今能夠看到一個 Events 的結構體, Rust 結構體目前先理解成其餘語言的 class
, 咱們能夠給一個 class
定義屬性, 還能夠添加構造方法, 通常的方法, 還能夠經過 private
, public
, protected
這類關鍵字控制屬性的訪問權限, Rust 結構體也具有這類特性, 不過有點區別的是, 沒有 protected
方面的控制. Rust 結構體沒有嚴格命名的構造方法, 根據慣例是使用 new
, 只要本身須要, 也可使用 create
, foo
, bar
... 之類的函數做爲構造方法.
Rust 一個很是好使的語法就是模式匹配, 比 Apple 每一年出的新語言模式匹配更容易玩. 功能強大, match
後面接一堆正則表達式均可以, 要啥自行車.oop
如今結構體定義了 quit
, key_escape
這些用來標註狀態修改的 bool
類型屬性, 而 pump
屬性是用來給內部的函數使用的, 不使用 pub
關鍵字來開放外部使用. 咱們看到 pump
函數有個 self
的參數, 這個參數能夠理解成表明結構體實例自己, 有了這個參數, 能夠在結構體實例調用本函數時, 經過 self
使用實例自身的屬性, 因爲咱們將準備在該函數內修改實例自身的屬性值, 因此使用 mut
來達到可變的效果. 至於 &
這個符號, 若是想讓實例調用 pump
函數後還能繼續使用, 得使用借用的方式傳 self
.ui
而後在 main.rs
中使用一下咱們的事件處理器spa
#![feature(uniform_paths)]
use sdl2::pixels::Color;
mod events;
use events::Events;
fn main() {
let sdl2_context = sdl2::init().unwrap();
let video = sdl2_context.video().unwrap();
let window = video
.window("Arcade Shooter", 800, 600)
.position_centered()
.opengl()
.build()
.unwrap();
let mut canvas = window.renderer().accelerated().build().unwrap();
canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear();
canvas.present();
let mut event = Events::new(sdl2_context.event_pump().unwrap());
'running: loop {
event.pump();
if event.quit || event.key_escape { break 'running; }
}
}
複製代碼
#![feature(uniform_paths)]
這一段是用來使用 Rust 的新特性, 由於我想簡單點使用咱們的 events
模塊, 以後就能夠直接在 main
函數內使用 Events
結構體了.線程
後面的邏輯很簡單, 每次在循環中調用一下 event.pump
來根據觸發的事件修改狀態, 判斷是否中止循環.
這一篇咱們使用一個帶標記的 loop
循環讓程序持續可用. 經過一個結構體, 使用 impl Foo
的方式給結構體添加函數, 瞭解到函數能夠經過 self
使用實例自身. 咱們還能使用 match
進行模式匹配來處理數據的多種狀況. 先這樣吧.