0x06. 窗口上的矩形

放個矩形

如今要在窗口上放一個矩形, 順便學習一下 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 行爲的定義, 就這樣吧, 以後再處理其餘的事體.

相關文章
相關標籤/搜索