雖然帶點小效果的飛船已經搞定了,可是如今背景一片黑,徹底沒看頭,其實加上紋理就能搞出背景,豈不美哉。canvas
作以前先總結一下思路,在 View
的 render
函數中,渲染飛船以前先把背景渲染出來,渲染背景其實就是加載紋理圖片,而後爲了製造視差效果,把不一樣背景向左移動,速度單獨設置,再加個前景在飛船以後加載渲染,同時設置移動速度,整體就是給一個飛船在太空中飛行的感受。函數
如今理清思路,實現一下邏輯,就是把行爲作抽象,既然要處理背景那就 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
處算好傳進去,同時 View
的 render
函數也要改一下,ShipView
也要改一下,緣由很簡單,ShipView
須要引入 Background
ui
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