はじめに
前回: RustでWindowに円を描く からの続きです。今回は、簡単なアニメーションをさせようと思います。
コード全体はこちらになります。
Rustでconrodを使って赤い円をアニメーションさせる
Waitを入れながらUI Eventを処理する
アニメーションさせるポイントの一つは、Main Loopの中でWaitを入れつつUI系Eventも処理することです。
元のサンプルにそういう処理があったので、似たような感じで下記のようにしています。
event.rs
pub fn next(&mut self, events_loop: &mut glium::glutin::EventsLoop, interval_ms: u64) -> Vec<glium::glutin::Event> {
let last_update = self.last_update;
let frame_interval_ms = std::time::Duration::from_millis(interval_ms);
let duration_since_last_update = std::time::Instant::now().duration_since(last_update);
if duration_since_last_update < frame_interval_ms {
std::thread::sleep(frame_interval_ms - duration_since_last_update);
}
// Collect all pending events.
let mut events = Vec::new();
events_loop.poll_events(|event| events.push(event));
self.last_update = std::time::Instant::now();
events
}
これを使って、
main.rs
let mut animation_loop = event::AnimationLoop::new();
'render: loop {
for event in animation_loop.next(&mut events_loop,
1000 / constants::FPS as u64) {
...
という感じでWaitを入れつつ、そのWaitしている間に発生した events を取り出すようになっています。
アニメーション処理を切り出しておく
今後、色々なアニメーションをやりたいので、おまじないだらけの main.rs
と分離しておくと気分が良さそうです。
animation.rs
use conrod_core;
use conrod_core::{widget, Positionable, Colorable, Widget};
widget_ids! {
struct Ids {
circle,
}
}
pub struct Animation {
n_frame: u64,
ids: Ids,
}
impl Animation {
pub fn new(ui: &mut conrod_core::Ui) -> Self {
Animation {
n_frame: 0,
ids: Ids::new(ui.widget_id_generator()),
}
}
pub fn next_frame(&mut self, ref mut ui: conrod_core::UiCell) {
self.n_frame += 1;
widget::Circle::fill(10.)
// 単に左から右に赤い円が動く
.xy([(((self.n_frame as i64) % 400)-200) as f64, 0.])
.color(conrod_core::color::RED)
.set(self.ids.circle, ui);
}
}
として、
main.rs
let mut anim = animation::Animation::new(&mut ui);
...
anim.next_frame(ui.set_widgets());
と使うようにしました。
今後アニメーション系の処理を変えたい場合は、 animation.rs
を変更するだけで良くなります(たぶん...)。
さいごに
大したことしてないですが、新しいものに触れるのは楽しいですね。