如今要在窗口上放一个矩形, 顺便学习一下 Rust 的其余语法.
咱们在 views
模块内写关于 rect
的结构体, 有一个不幸的消息, 以前写的 ViewA
ViewB
目前是用不上了, 以后视图切换之类的操做确定有用的, 如今咱们先把它们处理掉.canvas
来定义一个矩形的结构体, 一个矩形在窗口上有平面直角坐标系的 X 轴和 Y 轴的坐标和还有矩形自己的长宽.函数
若是想本身写矩形的渲染, 能够经过 OpenGL 来绘制两个三角形来组成一个矩形, 并且若是还要作矩形的移动等操做, 还要用线性代数的矩阵来作处理, 幸亏 SDL 提供了相关的 API 让咱们能够方便地绘制矩形学习
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Rectangle {
pub x: f64,
pub y: f64,
pub w: f64,
pub h: f64,
}
impl Rectangle {
pub fn to_sdl(&self) -> Option<SdlRect> {
assert!(self.w >= 0.0 && self.h >= 0.0);
Some(SdlRect::new(self.x as i32,
self.y as i32,
self.w as u32,
self.h as u32))
}
}
复制代码
关于 #[derive(Clone, Copy, Debug, PartialEq)]
这块, 通常的结构体经过 let
绑定到变量会发生全部权的 move
行为, 加了这 Clone
Copy
属性以后, 这个结构体进行变量绑定时就变得跟整型浮点型之类的类型同样的 copy
行为, 举例说明ui
let a: i32 = 10;
let b = a; // copy, a 还能被使用
struct Test {}
impl Test {
pub fn new() {
...
}
}
let c = Test::new();
let d = c; // move, c 全部权转移了
复制代码
关于 Debug
属性就是使结构体可让 println!
这些宏打印, PartialEq
就是让结构体可比较.spa
来定义个 RectView
结构体来实现一下 View
traitcode
struct Rect {
rect: Rectangle,
}
pub struct RectView {
player: Rect,
}
impl RectView {
pub fn new() -> Self {
Self {
player: Rect {
rect: Rectangle {
x: 64.0,
y: 64.0,
w: 32.0,
h: 32.0,
}
}
}
}
}
impl View for RectView {
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;
}
canvas.set_draw_color(Color::RGB(0, 50, 0));
canvas.clear();
canvas.set_draw_color(Color::RGB(200, 200, 50));
canvas.fill_rect(self.player.rect.to_sdl().unwrap())
.expect("fill rect fail");
ViewAction::None
}
}
复制代码
定义好这些东西以后, 再在 spawn
函数内把以前的 ViewA
改为 RectView
, 此外上面的代码值得注意的是要先 clear()
背景色, 再填充 rect
颜色事件
...
let mut current_view: Box<View> = box views::RectView::new();
...
复制代码
如今运行一下, 矩形已经渲染出来了.string
咱们发觉到, Rectangle
存储了矩形的宽高还有位置, 咱们如今只要修改这个结构体的值就能够改变矩形的宽高跟位置, 经过键盘的方向键来从新计算 x
, y
的值就能够达到让矩形移动的效果.it
按照惯例改一下事件宏的调用传入io
events_macro! {
keyboard: {
key_escape: Escape,
key_up: Up,
key_down: Down,
key_left: Left,
key_right: Right,
key_space: Space
},
else: {
quit: Quit { .. }
}
}
复制代码
而后在 render
函数中写从新计算值的逻辑, 如今方向键就四个, 而后咱们要来考虑全部的状况, 我以前的想法是一个一个用 if
去判断按键的触发, 可是明显这个方式写出来的代码太 ugly 了, 幸亏 Rust 模式匹配很是棒. 先来列一下会有的东西, 上下左右跟斜角移动, 这里定义个常量来做为移动的速度
const PLAYER_SPEED: f64 = 0.35;
impl View for RectView {
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;
}
let diagonal: bool = (events.key_up ^ events.key_down) &&
(events.key_left ^ events.key_right);
let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } *
PLAYER_SPEED;
let dx = match (events.key_left, events.key_right) {
(true, true) | (false, false) => 0.0,
(true, false) => -moved,
(false, true) => moved,
};
let dy = match (events.key_up, events.key_down) {
(true, true) | (false, false) => 0.0,
(true, false) => -moved,
(false, true) => moved,
};
self.player.rect.x += dx;
self.player.rect.y += dy;
canvas.set_draw_color(Color::RGB(0, 50, 0));
canvas.clear();
canvas.set_draw_color(Color::RGB(200, 200, 50));
canvas.fill_rect(self.player.rect.to_sdl().unwrap())
.expect("fill rect fail");
ViewAction::None
}
}
复制代码
至此已经能够在窗口上显示了矩形, 并且还能根据键盘方向键控制矩形移动, 了解到了 Rust 模式匹配的灵活运用, 结构体 copy
行为的定义, 就这样吧, 以后再处理其余的事体.