0x08. 添加遊戲背景

雖然帶點小效果的飛船已經搞定了,可是如今背景一片黑,徹底沒看頭,其實加上紋理就能搞出背景,豈不美哉。canvas

ship-bg

作以前先總結一下思路,在 Viewrender 函數中,渲染飛船以前先把背景渲染出來,渲染背景其實就是加載紋理圖片,而後爲了製造視差效果,把不一樣背景向左移動,速度單獨設置,再加個前景在飛船以後加載渲染,同時設置移動速度,整體就是給一個飛船在太空中飛行的感受。函數

如今理清思路,實現一下邏輯,就是把行爲作抽象,既然要處理背景那就 Background 結構體走起,結構體除了要顯示的紋理,還有自身的位置,以及平移速度,可是由於循環一直在執行,能夠採用時間來計算。 先把 Background 搞定oop

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;
        }
    }
}
複製代碼

elapsed 這個形參是經過計算後傳入的,因此在 spawn 函數內 loop 處算好傳進去,同時 Viewrender 函數也要改一下,ShipView 也要改一下,緣由很簡單,ShipView 須要引入 Backgroundui

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
    }
}
複製代碼

如今就能夠作到背景變化,因爲視差效果,咱們看起來就像飛船在不停往前移動。spa

相關文章
相關標籤/搜索