咱們已經肯定要讓主函數知道的更少, 在 phi
模塊內定義一個 spawn
函數, 入口只要調用這個函數, 就完成視圖的處理, 咱們要讓入口不須要了解到具體生成窗口之類的細節.canvas
pub fn spawn(title: &str) {
let sdl2_context = sdl2::init().unwrap();
let video = sdl2_context.video().unwrap();
let window = video
.window(title, 800, 600)
.position_centered()
.opengl()
.build()
.unwrap();
let canvas = window.renderer().accelerated().build().unwrap();
let events = Events::new(sdl2_context.event_pump().unwrap());
let mut context = Phi::new(events, canvas);
let mut current_view: Box<View> = box views::DefaultView;
'running: loop {
context.events.pump();
match current_view.render(&mut context) {
ViewAction::None => context.canvas.present(),
ViewAction::Quit => break 'running
}
}
}
複製代碼
如今主函數直接調用 spawn
就能夠了ide
fn main() {
phi::spawn("Arcade Shooter");
}
複製代碼
若是以前的代碼寫過的話, 可能發現其實 spawn
相較以前多了一個 box
的關鍵字, 若是使用的是 nightly
版本的 Rust, 能夠在 main.rs
處添加這個特性來啓用這個關鍵字函數
#![feature(box_syntax)]
複製代碼
要是不想用不穩定的特性, 就把使用 box
的地方改爲oop
Box::new(views::DefaultView)
複製代碼
爲何忽然用起了 Box<T>
, 引經據典一下, 根據官方的 Rust Book 的說法, 使用 Box<T>
的場景一般分ui
很明顯知足第三個使用場景, 咱們只須要關心一個值的特徵, 不須要關心它具體的類型, 就跟鴨子類型同樣, 走起來是鴨子, 叫起來是鴨子, 它本質上是否是鴨子並不重要, 咱們只要口感上是鴨子就行了.
如今只考慮一個值是否 impl View
就夠了, 因此這裏直接使用 Box<T>
.spa
如今執行一下能夠看到跟以前的效果沒什麼區別, 目前已經作到讓主函數變成甩手掌櫃了.code
咱們開發一個 iOS App, 一般都會涉及到多個控制器以前的切換, 如今這個應用, 也來實現一下視圖切換的事. 把處理事件的宏添加一下空格鍵的定義, 以後只要按了空格鍵就會觸發切換視圖的事件.事件
events_macro! {
keyboard: {
key_escape: Escape,
key_up: Up,
key_down: Down,
key_space: Space
},
else: {
quit: Quit { .. }
}
}
複製代碼
這時候不得再也不次感慨一下實現了宏的感受真贊.ip
而後在 views
的模塊內, 以前已經爲 DefaultView
實現了 View
這個 trait, 如今再來實現一個 ViewB
, DefaultView
也能夠更名成 ViewA
爲了好區分. 並且這裏能夠先寫上空格鍵觸發後的控制語句.ci
impl View for ViewB {
fn render(&mut self, context: &mut Phi) -> ViewAction {
let canvas = &mut context.canvas;
let events = &mut context.events;
if events.now.quit || events.now.key_escape == Some(true) {
return ViewAction::Quit;
}
if let Some(true) = events.now.key_space {}
canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear();
ViewAction::None
}
}
複製代碼
咱們在 loop
這塊有使用模式匹配的代碼, 使用到了 ViewAction 這個枚舉類型, 那就改一下 phi
模塊內的 ViewAction
的定義, 添加一個切換視圖的類型
pub enum ViewAction {
None,
Quit,
ChangeView(Box<View>),
}
複製代碼
活用各類數據類型能夠簡化解決不少問題, 如今再改一下兩個視圖結構體對於 View
的實現, 主要是剛纔的空格鍵事件判斷這塊
pub struct ViewA;
pub struct ViewB;
impl View for ViewA {
fn render(&mut self, context: &mut Phi) -> ViewAction {
......
if let Some(true) = events.now.key_space {
return ViewAction::ChangeView(box ViewB);
}
......
}
}
impl View for ViewB {
fn render(&mut self, context: &mut Phi) -> ViewAction {
......
if let Some(true) = events.now.key_space {
return ViewAction::ChangeView(box ViewA);
}
......
}
}
複製代碼
而後天然是修改 loop
內的代碼
'running: loop {
context.events.pump();
match current_view.render(&mut context) {
ViewAction::None => context.canvas.present(),
ViewAction::Quit => break 'running,
ViewAction::ChangeView(view) => current_view = view,
}
}
複製代碼
如今的效果就是點擊空格就會發生視圖改變, 爲了讓本身看得出來, 能夠把每一個視圖的背景色設置成不同的.
如今已經完成了簡化主函數的工做, 還搞定了視圖的切換. 以後再處理其餘方面的工做.