In the previous article, we showed a window using SDL2. What we did was let the thread sleep for 10 seconds to see what the window looked like. Now we want the window to close by actively triggering an event, and otherwise keep running.

To start, create a branch, git checkout -b events

Keep the window open

It’s easy to keep the window constantly displayed, through an endless loop, based on the original code.

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{}}Copy the code

Rust has a loop. ‘RUNNING’ can be ignored as a lifecycle tag. The current state of the program is not a normal state, after the program can be controlled by the user to close.

Allows Windows to be closed

Rust-sdl2 event control is provided in its Github repository examples. In this case, the event set of SDL2 is obtained by calling the event_pump function of sdL2_context. The loop iterates over the polling iterators obtained from the poll_iter function of the event set

let mut event_pump = sdl2_context.event_pump().unwrap();
'running: loop {
    for event in event_pump.poll_iter() {
        matchevent { Event::Quit {.. } | Event::KeyDown { keycode:Some(Keycode::Escape), .. } = > {break 'running}, _ => {}}}}Copy the code

The events we want to handle are the Quit event and the keypress escape. Now create a file called events.rs and put it in the same directory as 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::*;
            matchevent { Quit { .. } = >self.quit = true,
                KeyDown {
                    keycode: Some(Escape), .. } = >self.key_escape = true, _ => {}}}}}Copy the code

Now you can see a Events structure. The Rust structure is currently understood as a class of other languages. We can define attributes for a class and add constructors, common methods, private, public, The protected keyword controls access to properties. Rust also has this property, but there is no protected control. There are no strictly named constructors for Rust structures. The convention is to use new instead of create, foo, bar… Function as a constructor. One of Rust’s great syntax is pattern matching, which is much easier to play with than the new language pattern matching Apple releases every year. Powerful, match can be followed by a bunch of regular expressions, no bike.

The structure now defines attributes of type bool, such as quit and key_escape, to indicate state changes, while the pump attribute is used for internal functions without the pub keyword for external use. The pump function has an argument, self, that can be interpreted as representing the structure instance itself. With this argument, when the structure instance calls this function, we can use the property of the instance itself through self. Since we are going to modify the property value of the instance itself within the function, So use muT to achieve variable effects. As for the & symbol, if you want the instance to continue to use it after the pump function is called, you need to borrow self.

Then use our event handler in main.rs

#! [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; }}}Copy the code

#! The [feature(Uniform_paths)] section is used to use Rust’s new features, because I wanted to make it easier to use our Events module and then use the Events structure directly within the main function.

The logic behind this is simple: call event.pump each time in the loop to modify the state based on the triggered event and determine whether to stop the loop.


In this article we’ll use a marked loop to keep the program available. By adding functions to a structure using impl Foo, you learn that functions can use the instance itself through self. We can also use match for pattern matching to handle multiple cases of data. I’ll do that for now.