昨天大概講完 Rocket 的運用了
所以接下來就來介紹其他東西吧
這次要講的是 Game Engine
目前 Rust 裡面比較大的遊戲引擎有兩個
這次我會介紹 Bevy 因為他比較簡單易用
而 RG3D 他可以應付比較大的場景
也有編輯器
整體來說目前 RG3D 的前景是良好的
而 Bevy 也正在快速發展中
Bevy 是以 ECS 存儲和管理所有數據
簡單來說就是在資料庫中。不同數據類型以表的「列」,並且可以存在包含實體的「行」。
比如說給予一個玩家結構血量 還有攻擊力跟防禦值 這樣的概念
那本篇使用版本是 Bevy 0.5.0
且本次不會介紹 Example 直衝專案
那專案的部份我是直接去撰寫的所以可能進度上比較緩慢 可能 30 天內寫不完
但是我盡量
讓我們開始吧!
首先起手式
$ cargo add bevy
就這樣 不用添加其他東西了 應該目前也只會用到這個
我想做的是類似於 Undertale 對決 Undyne 時的小遊戲
但是簡化很多 就單純箭頭飄過去而已
大概這種感覺
好OK 開始ㄅ
今天會做的是 創建會移動的物件
fn main() {
App::build()
.insert_resource(WindowDescriptor {
title: "owo!".to_string(),
width: 800.,
height: 600.,
..Default::default()
})
.insert_resource(ClearColor(Color::rgb(1., 0.4, 0.4)))
.run();
}
首先會長這樣
就是我們的 main function
那這邊主要是創建一個視窗
並且我們給他 長寬 標題以及顏色
fn setup(mut commands: Commands) {
commands
.spawn_bundle(OrthographicCameraBundle::new_2d())
.commands()
.spawn_bundle(UiCameraBundle::default());
}
然後這邊是設置 camera 的部份
因為我們是 2D 遊戲所以就直接設置一個 2D 場景
那麼由於我們 ECS 的特性所以在我們要使用材質的時候也要對物件歸類
pub struct ArrowMaterial {
up: Handle<ColorMaterial>,
down: Handle<ColorMaterial>,
left: Handle<ColorMaterial>,
right: Handle<ColorMaterial>,
}
其實不一定要用 pub 但是我只是怕 Debug 麻煩
impl FromWorld for ArrowMaterial {
fn from_world(world: &mut World) -> Self {
let world = world.cell();
let mut material = world.get_resource_mut::<Assets<ColorMaterial>>().unwrap();
let asset_server = world.get_resource::<AssetServer>().unwrap();
let up = asset_server.load("up.png");
let down = asset_server.load("down.png");
let left = asset_server.load("left.png");
let right = asset_server.load("right.png");
ArrowMaterial {
up: material.add(up.into()),
down: material.add(down.into()),
left: material.add(left.into()),
right: material.add(right.into()),
}
}
}
至於這邊的部份可以看到說我讓他去讀取了圖片資源
而資源位置會位於 assets 資料夾中
也就是現在檔案目錄應該要長這樣
這邊的部份沒有什麼技術成份 直接抄就好了
雖然當初也是想很久 第一次寫的時候
pub fn spawn_arrow_up(mut commands: Commands,
materials: Res<ArrowMaterial>,
time: Res<Time>,
mut timer: ResMut<SpawnTimer>) {
if timer.0.tick(time.delta()).just_finished() {
let transform = Transform::from_translation(Vec3::new(0., -450., 1.));
commands
.spawn_bundle(SpriteBundle {
material: materials.up.clone(),
sprite: Sprite::new(Vec2::new(100., 100.)),
transform,
..Default::default()
})
.insert(UpArrow);
}
}
那麼既然講完材質 固然要講一下如何讓物件出現在場景上
而這邊我讓他去讀秒 也就是會隨著時間生成
pub struct SpawnTimer(pub Timer);
所以記得要定義好 Struct
這邊可以看到說我使用了一個 transform
而也代表了物件的 x, y, z
至於 z 的部份由於我們是 2D 遊戲所以不會有任何影響
然後材質記得要用 clone 的新增
而 sprite 是大小的意思 可以自己設定
fn up_arrows(time: Res<Time>, mut query: Query<(&mut Transform, &UpArrow)>) {
for (mut transform, _arrow) in query.iter_mut() {
transform.translation.y += time.delta_seconds() * 200.;
}
}
而這邊的部份就比較簡單了
就是隨著時間去更改他的位置
而也因為他時間是使用 float 所以看起來會是緩慢移動的感覺
後面的 200. 是速度
然後上面的 for 迴圈是 tuple 是因為他包含了兩個項目
總之大概這樣
早上起來才發現有地方少講
基本上要使用弄好的 function
就只要在 main function 裡面 在 App build 那邊的最下面使用 .add_system(<函數名稱>.system())
要注意的是 函數名稱不包含 ()
明天我們來講另一個統整的方法
而最後運行會長這樣
而其他四個方向就由讀者自行操作了
今天大概這樣 打 BNT 手有點痛