上一篇已经使用 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
进行模式匹配来处理数据的多种状况. 先这样吧.