HEXA BLOG
ヘキサブログ
プログラム
rustが難しい話-入門編
sudoやsuがrustで書き直されるプロジェクトが予定されていると聞いて
ついにrustの時代到来か⁉とワクワクが止まらないgood sun🌞こと山口です。
windowsのinsider版にもrust製のプログラムが含まれ始めるようですね。
今回はそんなrustを従来の思考で使用すると難しいという話です。
今回はゲームループの中での要素ごとの振る舞いをポリモーフィズムを使って書く簡単なサンプルを書いて見ました。
ソースは全文は以下の通りです。
流れとしては2種類のユニットを更新して寿命が尽きたら後継のユニットを生成してそれを管理するというのを永遠と繰り返すだけのプログラムです。
今回はC++的な感覚でtraitを使って実装してみます。
rustにはclassや継承が無くinterface的な機能を持つのがtraitです。
こんな感じで更新処理と死亡判定を持つようなtraitを定義します
trait Task {
fn update(&mut self);
fn is_died(&self)->bool;
fn spawn(&self)->Box<dyn Task>;
}
そしてstructにtraitを実装します
struct UnitA {
name : String,
life : i32,
}
impl Task for UnitA{
fn update(&mut self){
self.life -= 1;
println!(“{}’s life remain {}”, self.name, self.life);
}
fn is_died(&self)->bool {
self.life <= 0
}
fn spawn(&self)->Box<dyn Task>{
println!(“UnitA spawn UnitB”);
Box::new(UnitB::new())
}
}
一通りの定義が出来たらこれらを可変長配列のVec<T>でインスタンスを保持するように書きます。
let mut units: Vec<Box<dyn Task>> = vec![
Box::new(UnitA::new()),
Box::new(UnitB::new())
];
大事なのはBoxを使ってヒープにデーターを格納します。
直接Vec<dyn Task>で定義するとコンパイルエラーです。
まずはこの辺でどうして?という気持ちになってきます。
そして初期データーの設定が出来たら
ユニット毎に更新を掛けたあとに生き死にチェックをして、死亡していたら死亡後の後継ユニットを作成して配列から取り除くというのをやって見ます。
ここを以下の様に書くと
let unit = units[i].as_mut();
unit.update();
if unit.is_died(){
println!(“unit is died remove”);
units.push(unit.spawn());
units.remove(i);
}
else{
i += 1;
}
以下の様に怒られます
let unit = units[i].as_mut();
—– first mutable borrow occurs hereunits.push(unit.spawn());
^^^^^^^^^^^————^
| |
| first borrow later used here
second mutable borrow occurs here
Rustさんの真骨頂の借用チェッカーが仕事をしてくれています。
プログラム的にはunitからspawn()したものをunitsにpushしていると記述しているつもりですがrustの文法的には違うのかもしれません。どうしてそうなのか理解していないです。😋
これの対策として別のVecに追加変数作ったりもしましたが、最終的に記述順番で対処しました、この辺が分かるまでちょっと時間かかりました。
(因みにif unit.is_died(){をC++のノリでif(unit.is_died()){と書くとコンパイラが警告を発生させてくれます)
そして一通り出来たので実行してみます。
意図したとおりに動きました、一安心です。
今回一件意図したように動いているように見えますが実は問題があります。
Boxを使って単一の参照のみで動作させる場合はこれで良いのですが、
実際のゲームでは他の要素を参照したり、そこに変更を加える必要が出てきます。
そう言ったことをやる為にリファレンスカウンター等に手を出していくと
どんどんとコンパイルエラーが発生していきます😥。
今回はその辺まで欲張ろうとしたらごちゃごちゃしてきたので入門程度に簡単にまとめました。
入門レベルでも予期せぬコンパイルエラーによってrustの安全性が伝わってきますね。
これ以上のゲーム向けの作りにするにはC++での作り方の感覚から変えていく必要がありそうです。
次回はこの辺やマルチスレッド化に触れたいと考えています。では。👋
CATEGORY
- about ヘキサ (166)
- 部活動 (6)
- CG (18)
- プロジェクトマネジメント (1)
- 研修 (5)
- 美学 (1)
- いいモノづくり道 (230)
- 採用 -お役立ち情報も- (149)
- プログラム (188)
- デザイン (99)
- ゲーム (274)
- 日記 (1,104)
- 書籍紹介 (113)
- その他 (875)
- 就活アドバイス (20)
- ラーメン (3)
- ライフハック (25)
- イベント紹介 (10)
- 料理 (23)
- TIPS (7)
- 怖い話 (3)
- サウンド (5)
- 子育て (1)
- 筋トレ (1)
- 商品紹介 (21)
- アプリ紹介 (31)
- ソフトウェア紹介 (33)
- ガジェット紹介 (12)
- サイト紹介 (10)
- 研究・開発 (34)
- 回路図 (4)
- アナログゲーム (40)
- 交流会 (21)
- 報告会 (3)
- インフラ (25)
- グリとブラン (6)
- カメラ (9)
- クラフト (27)
- 部活 (14)
- 画伯 (15)
- カレー (6)
- 音楽(洋楽) (6)
- 映画・舞台鑑賞 (43)
- 飼育 (5)
- いぬ (8)
- ねこ (19)
ARCHIVE
- 2024年
- 2023年
- 2022年
- 2021年
- 2020年
- 2019年
- 2018年
- 2017年
- 2016年
- 2015年
- 2014年
- 2013年
- 2012年
- 2011年
- 2010年
- 2009年
- 2008年
- 2007年