Macroquad Rust 遊戲開發 Kyle 型別宣告 let x = 32; // 自動型別推斷
x = 24; // *FIXME* 變數預設不可改變
let mut x = 10; // 需加 `mut` 才可更換
2 / 35 字串 3 / 35 字串 • 在 rust 中,以雙引號建造的字串("Kyle"),為不可變字串,型別為 &str
4 / 35 字串 • 在 rust 中,以雙引號建造的字串("Kyle"),為不可變字串,型別為 &str
• 只是一個記憶體區塊的不可變借用(指標) 5 / 35 字串 • 在 rust 中,以雙引號建造的字串("Kyle"),為不可變字串,型別為 &str
• 只是一個記憶體區塊的不可變借用(指標) • 若要建造一個可以改變自身記憶體的字串,則需利用 String
6 / 35 字串 • 在 rust 中,以雙引號建造的字串("Kyle"),為不可變字串,型別為 &str
• 只是一個記憶體區塊的不可變借用(指標) • 若要建造一個可以改變自身記憶體的字串,則需利用 String
▍ technical info: &str 儲存在 stack 上、String 儲存在 heap 上
let mut s = "kyle";
s = "cheng"; // 合法!因為只是單純改變借用的標的
s.push_str("@") // 不合法!因為不可以改變記憶體中所儲存的內容
7 / 35 字串 • 在 rust 中,以雙引號建造的字串("Kyle"),為不可變字串,型別為 &str
• 只是一個記憶體區塊的不可變借用(指標) • 若要建造一個可以改變自身記憶體的字串,則需利用 String
▍ technical info: &str 儲存在 stack 上、String 儲存在 heap 上
let mut s = String::from("kyle");
s.push_str("@") // 合法!
8 / 35 枚舉 • 枚舉在 Rust 中所代表的是,將所有可能的狀態給封裝起來。
9 / 35 枚舉 • 枚舉在 Rust 中所代表的是,將所有可能的狀態給封裝起來。
enum MaybeInt {
Some(i32)
None
}
let x = MaybeInt::Some(3);
10 / 35 枚舉 • 枚舉在 Rust 中所代表的是,將所有可能的狀態給封裝起來。
enum MaybeInt {
Some(i32)
None
}
let x = MaybeInt::Some(3);
• 若要將枚舉中的值,「提取」出來,則需利用 match
11 / 35 match let x = MaybeInt::Some(3);
match x {
MaybeInt::Some(value) => {
println!("{}!", value);
}
None => {
println!("Nothing is contained!");
}
}
12 / 35 Vector • 在 Rust 中,類型名為 Vec,代表整個數組只能儲存同一種型別
let v = vec![1,2,3];
let first_element = v[0];
match v.get(2) {
Some(third) => println!("Third element exists! {}", x),
None => println!("Damn nothing exists.")
}
13 / 35 函數和 for 迴圈 fn print_odds(v: Vec<i32>) -> i32 {
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 14 / 35 函數和 for 迴圈 • fn name() -> return_type
fn print_odds(v: Vec<i32>) -> i32 {
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 15 / 35 函數和 for 迴圈 • fn name() -> return_type
fn print_odds(v: Vec<i32>) -> i32 { • for i in 1..=3 or for i in 1..4
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 16 / 35 函數和 for 迴圈 • fn name() -> return_type
fn print_odds(v: Vec<i32>) -> i32 { • for i in 1..=3 or for i in 1..4
for x in v { • println!("{}", value) 利用 {} 來輸出變數
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 17 / 35 函數和 for 迴圈 • fn name() -> return_type
fn print_odds(v: Vec<i32>) -> i32 { • for i in 1..=3 or for i in 1..4
for x in v { • println!("{}", value) 利用 {} 來輸出變數
if x % 2 == 1 { • fn main() 為全部程式開始處
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 18 / 35 函數和 for 迴圈 • fn name() -> return_type
fn print_odds(v: Vec<i32>) -> i32 { • for i in 1..=3 or for i in 1..4
for x in v { • println!("{}", value) 利用 {} 來輸出變數
if x % 2 == 1 { • fn main() 為全部程式開始處
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let x = "rust";
println!("hello {}", x);
println!("ans {}", print_odds(vec![1,2,3,4,5]));
}
snippet +exec is disabled, run with -x to enable 19 / 35 擁有權與借用 fn print_odds(v: Vec<i32>) -> i32 {
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(v));
// v 不可再使用
}
20 / 35 擁有權與借用 • 由於 vec![1,2,3,4,5] 這塊記憶體的所有權被轉移至
fn print_odds(v: Vec<i32>) -> i32 { print_odds
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(v));
// v 不可再使用
}
21 / 35 擁有權與借用 • 由於 vec![1,2,3,4,5] 這塊記憶體的所有權被轉移至
fn print_odds(v: Vec<i32>) -> i32 { print_odds
for x in v { • 若要使 v 在 print_odds 仍能夠使用,則需利用借用
if x % 2 == 1 { 來避免轉移所有權
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(v));
// v 不可再使用
}
22 / 35 擁有權與借用 • 由於 vec![1,2,3,4,5] 這塊記憶體的所有權被轉移至
fn print_odds(v: Vec<i32>) -> i32 { print_odds
for x in v { • 若要使 v 在 print_odds 仍能夠使用,則需利用借用
if x % 2 == 1 { 來避免轉移所有權
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(v));
// v 不可再使用
}
23 / 35 擁有權與借用 fn print_odds(v: &Vec<i32>) -> i32 {
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(&v));
// v 可再使用
}
24 / 35 擁有權與借用 • 添加 & 至型別或值可使其變為借用的版本
fn print_odds(v: &Vec<i32>) -> i32 {
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(&v));
// v 可再使用
}
25 / 35 擁有權與借用 • 添加 & 至型別或值可使其變為借用的版本
fn print_odds(v: &Vec<i32>) -> i32 { • 借用版本的值不可被更改
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(&v));
// v 可再使用
}
26 / 35 擁有權與借用 • 添加 & 至型別或值可使其變為借用的版本
fn print_odds(v: &Vec<i32>) -> i32 { • 借用版本的值不可被更改
for x in v {
if x % 2 == 1 {
println!("{} is odd!", x);
} else {
println!("{} is even!", x);
}
}
return 20;
}
fn main() {
let v = vec![1,2,3,4,5];
println!("ans {}", print_odds(&v));
// v 可再使用
}
27 / 35 結構體 struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 28 / 35
}
結構體 • 利用 &self 獲取結構體欄位中所儲存的資料
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 29 / 35
}
結構體 • 利用 &self 獲取結構體欄位中所儲存的資料
struct User { • 可直接利用 User {} 初始化
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 30 / 35
}
結構體 • 利用 &self 獲取結構體欄位中所儲存的資料
struct User { • 可直接利用 User {} 初始化
active: bool, • 利用 .method() 呼叫具 &self 的 method
username: String,
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 31 / 35
}
結構體 • 利用 &self 獲取結構體欄位中所儲存的資料
struct User { • 可直接利用 User {} 初始化
active: bool, • 利用 .method() 呼叫具 &self 的 method
username: String, • 利用 ::method() 呼叫不具有 &self 的 method
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 32 / 35
}
結構體 • 利用 &self 獲取結構體欄位中所儲存的資料
struct User { • 可直接利用 User {} 初始化
active: bool, • 利用 .method() 呼叫具 &self 的 method
username: String, • 利用 ::method() 呼叫不具有 &self 的 method
email: String,
sign_in_count: u64,
}
impl User {
fn new() -> User {
User {
active: true,
username: String::from("baby"),
email: String::from("hello"),
sign_in_count: 24,
}
}
fn print_details(&self) {
println!("email: {}", self.email);
println!("activeness: {}", self.active);
}
}
fn main() {
let s = User::new();
s.print_details(); 33 / 35
}
Macroquad • 與 pygame 類似、具「畫畫」功能 • 這就是每一個 macroquad 程式所需的模版
• 以下是一堆「方便」函數 use macroquad::prelude::*;
// functions!
fn draw_rectangle(...) { ... } #[macroquad::main("YourApplicationName")]
fn draw_line(...) { ... } async fn main() {
fn draw_text(...) { ... } loop {
fn draw_circle(...) { ... } clear_background(RED);
fn clear_background() { ... }
fn is_key_down(key: KeyCode) { ... } // ... 將你的程式放這裡!
fn get_time() -> f64 { ... }
fn screen_width() -> f64 { ... } next_frame().await
fn screen_height() -> f64 { ... } }
// colors! 請倚靠 autocomplete }
macroquad::colors::{ ... }
34 / 35 (RandGenerator)
▍ https://docs.rs/macroquad/latest/macroquad/rand/struct.RandGenerator.html
具有以下 methods • pub const fn new() -> RandGenerator
• pub fn srand(&self, seed: u64)
• pub fn rand(&self) -> u32
• pub fn gen_range<T>(&self, low: T, high: T) -> T where T: RandomRange
gen_range 使用方法如下
use macroquad::prelude::*;
fn main() {
rand::srand(miniquad::date::now().to_bits());
let v = rand::gen_range(0, 32);
println!("{}", v);
}
35 / 35