Although the ship with a small effect is done, now the background is black, completely unimpressive, in fact, add texture to create the background, isn’t beautiful.

Do before you summarize the train of thought, in the View of the render function, rendering the spacecraft before the background rendering, rendering the background is actually loaded texture images, and then to make the parallax effect, the different background moving to the left, speed setting alone, plus a prospect in ship after loading rendering, set speed at the same time, The overall idea is to give a spacecraft the feel of flying in space.

Now, to get the idea straight, to implement the logic, to make the behavior abstract, since we’re dealing with the Background, let’s start with the Background structure, the structure, in addition to the texture to display, but also its position, and translation speed, but because the loop is always executing, you can use time to calculate. So let’s do the Background

impl Sprite {
    pub fn size(&self) - > (f64.f64) {(self.src.w, self.src.h)
    }
}

#[derive(Clone)]
struct Background {
    pos: f64,
    vel: f64,
    sprite: Sprite,
}
impl Background {
    fn render(&mut self, canvas: &mut Renderer, elapsed: f64) {
        let (w, h) = self.sprite.size();
        self.pos += self.vel * elapsed;

        if self.pos > w {
            self.pos -= w;
        }

        let (win_w, win_h) = canvas.output_size().unwrap();
        let scale = win_h as f64 / h;
        let mut physical_left = -self.pos * scale;
        while physical_left < win_w as f64 {
            canvas.copy_sprite(&self.sprite,
                               Rectangle {
                                   x: physical_left,
                                   y: 0.0,
                                   w: w * scale,
                                   h: win_h as f64}); physical_left += w * scale; }}}Copy the code

Elapsed is passed in by calculation, so count it in the spawn loop, change the render function of the View, and change the ShipView as well, for the simple reason that Background is required for ShipView

pub struct ShipView {
    player: Ship,
    bg_back: Background,
    bg_middle: Background,
    bg_front: Background,
}
impl ShipView {
    pub fn new(phi: &mut Phi) -> Self {
        // ...
        Self {
            player: Ship {
                rect: Rectangle {
                    x: 64.0,
                    y: 64.0,
                    w: 32.0,
                    h: 32.0,
                },
                sprites,
                current: ShipFrame::MidNorm,
            },
            bg_front: Background {
                pos: 0.0,
                vel: 80.0,
                sprite: Sprite::load(&mut phi.canvas,
                "assets/star_fg.png").unwrap(),
            },
            bg_middle: Background{
                pos: 0.0,
                vel: 40.0,
                sprite: Sprite::load(&mut phi.canvas,
                "assets/star_mg.png").unwrap(),
            },
            bg_back: Background{
                pos: 0.0,
                vel: 20.0,
                sprite: Sprite::load(&mut phi.canvas,
                "assets/star_bg.png").unwrap(),
            }
        }
    }
}

pub trait View {
    fn render(&mut self, context: &mut Phi, elapsed: f64) -> ViewAction;
}

pub fn spawn(title: &str) {
    // ...
    let mut timer = sdl2_context.timer().unwrap();
    let interval = 1000 / 60;
    let mut before = timer.ticks();
    'running: loop {
        let now = timer.ticks();
        let dt = now - before;
        let elapsed = dt  as f64 / 1000.0;
        if dt < interval {
            timer.delay(interval - dt);
            continue;
        }
        before = now;
        context.events.pump(&mut context.canvas);
        match current_view.render(&mut context, elapsed) {
            ViewAction::None => context.canvas.present(),
            ViewAction::Quit => break 'running,}}}impl View for ShipView {
    fn render(&mut self, context: &mut Phi, elapsed: f64) -> ViewAction {
        // ...
        canvas.set_draw_color(Color::RGB(0.0.0));
        canvas.clear();

        self.bg_back.render(canvas, elapsed);
        self.bg_middle.render(canvas, elapsed);
        // ...
        canvas.copy_sprite(
            &self.player.sprites[self.player.current as usize].self.player.rect);

        self.bg_front.render(canvas, elapsed);
        ViewAction::None}}Copy the code

Now you can do the background change, and because of the parallax effect, it looks like the ship is moving forward.