博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
0x05. 视图操作
阅读量:6069 次
发布时间:2019-06-20

本文共 3672 字,大约阅读时间需要 12 分钟。

简化主函数

我们已经确定要让主函数知道的更少, 在 phi 模块内定义一个 spawn 函数, 入口只要调用这个函数, 就完成视图的处理, 我们要让入口不需要了解到具体生成窗口之类的细节.

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
= box views::DefaultView; 'running: loop { context.events.pump(); match current_view.render(&mut context) { ViewAction::None => context.canvas.present(), ViewAction::Quit => break 'running } }}复制代码

现在主函数直接调用 spawn 就可以了

fn main() {    phi::spawn("Arcade Shooter");}复制代码

如果之前的代码写过的话, 可能发现其实 spawn 相较之前多了一个 box 的关键字, 如果使用的是 nightly 版本的 Rust, 可以在 main.rs 处添加这个特性来启用这个关键字

#![feature(box_syntax)]复制代码

要是不想用不稳定的特性, 就把使用 box 的地方改成

Box::new(views::DefaultView)复制代码

为什么突然用起了 Box<T>, 引经据典一下, 根据官方的 Rust Book 的说法, 使用 Box<T> 的场景通常分

  • When you have a type whose size can’t be known at compile time and you want to use a value of that type in a context that requires an exact size
  • When you have a large amount of data and you want to transfer ownership but ensure the data won’t be copied when you do so
  • When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type

很明显满足第三个使用场景, 我们只需要关心一个值的特征, 不需要关心它具体的类型, 就跟鸭子类型一样, 走起来是鸭子, 叫起来是鸭子, 它本质上是不是鸭子并不重要, 我们只要口感上是鸭子就好了.

现在只考虑一个值是否 impl View 就够了, 所以这里直接使用 Box<T>.

现在执行一下可以看到跟之前的效果没什么区别, 目前已经做到让主函数变成甩手掌柜了.

视图之间的切换

我们开发一个 iOS App, 通常都会涉及到多个控制器之前的切换, 现在这个应用, 也来实现一下视图切换的事. 把处理事件的宏添加一下空格键的定义, 之后只要按了空格键就会触发切换视图的事件.

events_macro! {    keyboard: {        key_escape: Escape,        key_up: Up,        key_down: Down,        key_space: Space    },    else: {        quit: Quit { .. }    }}复制代码

这时候不得不再次感慨一下实现了宏的感觉真赞.

然后在 views 的模块内, 之前已经为 DefaultView 实现了 View 这个 trait, 现在再来实现一个 ViewB, DefaultView 也可以改名成 ViewA 为了好区分. 而且这里可以先写上空格键触发后的控制语句.

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 的实现, 主要是刚才的空格键事件判断这块

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,    }}复制代码

现在的效果就是点击空格就会发生视图改变, 为了让自己看得出来, 可以把每个视图的背景色设置成不一样的.


现在已经完成了简化主函数的工作, 还搞定了视图的切换. 之后再处理其他方面的工作.

转载地址:http://kifgx.baihongyu.com/

你可能感兴趣的文章
VS 一些用法设置
查看>>
深入 HBase 架构解析(1)
查看>>
三:JMS消息服务规范
查看>>
初玩OpenWRT之编译TP-Link WR841N V8固件
查看>>
[Everyday Mathematics]20150103
查看>>
iOS 数据库离线缓存思路和网络层封装
查看>>
JAVA编程中的类和对象
查看>>
linux中必会的目录
查看>>
SpringMVC实现ajax文件上传
查看>>
如何在各种编程语言中生成安全的随机数
查看>>
第十五回(一):文会内战平分秋色 树下阔论使坏心焦
查看>>
获取本机 Android 默认sha1 秘钥
查看>>
深度解析dba_segments和sys.seg$中的细节差异(上)
查看>>
Oracle分区数据问题的分析和修复
查看>>
打通钉钉+WebHook: 日志服务(SLS)告警实践
查看>>
29.8. sshpass - noninteractive ssh password provider
查看>>
双栈队列实现快速获取队列最大值最小值
查看>>
[20150430]列删除的简单恢复.txt
查看>>
Java Class类的使用 和 动态加载类
查看>>
2017深度学习NLP进展与趋势
查看>>