summaryrefslogtreecommitdiffstats
path: root/examples/game_of_life
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-02 09:27:49 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-02 09:27:49 +0200
commit0025b8c3f8f029d6fb7b8b5a599cc6450248aad6 (patch)
treeb9fc117c9df861207ed0508d57dc43f49a4b9919 /examples/game_of_life
parent916a1bfc7049867669b81f446e711021d92a4132 (diff)
downloadiced-0025b8c3f8f029d6fb7b8b5a599cc6450248aad6.tar.gz
iced-0025b8c3f8f029d6fb7b8b5a599cc6450248aad6.tar.bz2
iced-0025b8c3f8f029d6fb7b8b5a599cc6450248aad6.zip
Display some statistics in `game_of_life`
Diffstat (limited to 'examples/game_of_life')
-rw-r--r--examples/game_of_life/src/main.rs104
-rw-r--r--examples/game_of_life/src/style.rs38
2 files changed, 119 insertions, 23 deletions
diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs
index b8cabf24..b77d06ea 100644
--- a/examples/game_of_life/src/main.rs
+++ b/examples/game_of_life/src/main.rs
@@ -26,6 +26,8 @@ struct GameOfLife {
next_button: button::State,
clear_button: button::State,
speed_slider: slider::State,
+ tick_duration: Duration,
+ tick_amount: usize,
}
enum State {
@@ -71,7 +73,12 @@ impl Application for GameOfLife {
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Grid(message) => {
- self.grid.update(message);
+ if let Some((tick_duration, tick_amount)) =
+ self.grid.update(message)
+ {
+ self.tick_duration = tick_duration;
+ self.tick_amount = tick_amount;
+ }
}
Message::Tick(_) | Message::Next => match &mut self.state {
State::Paused => {
@@ -86,7 +93,7 @@ impl Application for GameOfLife {
let needed_ticks =
(self.speed as f32 * seconds_elapsed).ceil() as usize;
- if let Some(task) = self.grid.tick(needed_ticks) {
+ if let Some(task) = self.grid.tick(needed_ticks.max(1)) {
*last_tick = Instant::now();
if let Some(speed) = self.next_speed.take() {
@@ -154,33 +161,49 @@ impl Application for GameOfLife {
let selected_speed = self.next_speed.unwrap_or(self.speed);
let speed_controls = Row::new()
+ .width(Length::Fill)
+ .align_items(Align::Center)
.spacing(10)
.push(
Slider::new(
&mut self.speed_slider,
- 1.0..=100.0,
+ 1.0..=1000.0,
selected_speed as f32,
Message::SpeedChanged,
)
- .width(Length::Units(200))
.style(style::Slider),
)
- .push(Text::new(format!("x{}", selected_speed)).size(16))
- .align_items(Align::Center);
+ .push(Text::new(format!("x{}", selected_speed)).size(16));
+
+ let stats = Column::new()
+ .width(Length::Units(150))
+ .align_items(Align::Center)
+ .spacing(2)
+ .push(
+ Text::new(format!("{} cells", self.grid.cell_count())).size(14),
+ )
+ .push(
+ Text::new(format!(
+ "{:?} ({})",
+ self.tick_duration, self.tick_amount
+ ))
+ .size(14),
+ );
let controls = Row::new()
.padding(10)
.spacing(20)
+ .align_items(Align::Center)
.push(playback_controls)
.push(speed_controls)
+ .push(stats)
.push(
Button::new(&mut self.clear_button, Text::new("Clear"))
.on_press(Message::Clear)
- .style(style::Button),
+ .style(style::Clear),
);
let content = Column::new()
- .align_items(Align::Center)
.push(self.grid.view().map(Message::Grid))
.push(controls);
@@ -199,6 +222,7 @@ mod grid {
};
use rustc_hash::{FxHashMap, FxHashSet};
use std::future::Future;
+ use std::time::{Duration, Instant};
pub struct Grid {
state: State,
@@ -214,6 +238,8 @@ mod grid {
Populate(Cell),
Ticked {
result: Result<Life, TickError>,
+ tick_duration: Duration,
+ tick_amount: usize,
version: usize,
},
}
@@ -240,16 +266,29 @@ mod grid {
const MIN_SCALING: f32 = 0.1;
const MAX_SCALING: f32 = 2.0;
+ pub fn cell_count(&self) -> usize {
+ self.state.cell_count()
+ }
+
pub fn tick(
&mut self,
amount: usize,
) -> Option<impl Future<Output = Message>> {
- use iced::futures::FutureExt;
-
let version = self.version;
let tick = self.state.tick(amount)?;
- Some(tick.map(move |result| Message::Ticked { result, version }))
+ Some(async move {
+ let start = Instant::now();
+ let result = tick.await;
+ let tick_duration = start.elapsed() / amount as u32;
+
+ Message::Ticked {
+ result,
+ version,
+ tick_duration,
+ tick_amount: amount,
+ }
+ })
}
pub fn clear(&mut self) {
@@ -259,25 +298,36 @@ mod grid {
self.cache.clear();
}
- pub fn update(&mut self, message: Message) {
+ pub fn update(
+ &mut self,
+ message: Message,
+ ) -> Option<(Duration, usize)> {
match message {
Message::Populate(cell) => {
self.state.populate(cell);
- self.cache.clear()
+ self.cache.clear();
+
+ None
}
Message::Ticked {
result: Ok(life),
version,
+ tick_duration,
+ tick_amount,
} if version == self.version => {
self.state.update(life);
- self.cache.clear()
+ self.cache.clear();
+
+ Some((tick_duration, tick_amount))
}
Message::Ticked {
result: Err(error), ..
} => {
dbg!(error);
+
+ None
}
- Message::Ticked { .. } => {}
+ Message::Ticked { .. } => None,
}
}
@@ -478,6 +528,10 @@ mod grid {
}
impl State {
+ fn cell_count(&self) -> usize {
+ self.life.len() + self.births.len()
+ }
+
fn contains(&self, cell: &Cell) -> bool {
self.life.contains(cell) || self.births.contains(cell)
}
@@ -533,6 +587,18 @@ mod grid {
}
impl Life {
+ fn len(&self) -> usize {
+ self.cells.len()
+ }
+
+ fn contains(&self, cell: &Cell) -> bool {
+ self.cells.contains(cell)
+ }
+
+ fn populate(&mut self, cell: Cell) {
+ self.cells.insert(cell);
+ }
+
fn tick(&mut self) {
let mut adjacent_life = FxHashMap::default();
@@ -559,14 +625,6 @@ mod grid {
}
}
- fn contains(&self, cell: &Cell) -> bool {
- self.cells.contains(cell)
- }
-
- fn populate(&mut self, cell: Cell) {
- self.cells.insert(cell);
- }
-
pub fn iter(&self) -> impl Iterator<Item = &Cell> {
self.cells.iter()
}
diff --git a/examples/game_of_life/src/style.rs b/examples/game_of_life/src/style.rs
index 0becb5be..d59569f2 100644
--- a/examples/game_of_life/src/style.rs
+++ b/examples/game_of_life/src/style.rs
@@ -6,6 +6,12 @@ const ACTIVE: Color = Color::from_rgb(
0xDA as f32 / 255.0,
);
+const DESTRUCTIVE: Color = Color::from_rgb(
+ 0xC0 as f32 / 255.0,
+ 0x47 as f32 / 255.0,
+ 0x47 as f32 / 255.0,
+);
+
const HOVERED: Color = Color::from_rgb(
0x67 as f32 / 255.0,
0x7B as f32 / 255.0,
@@ -55,6 +61,38 @@ impl button::StyleSheet for Button {
}
}
+pub struct Clear;
+
+impl button::StyleSheet for Clear {
+ fn active(&self) -> button::Style {
+ button::Style {
+ background: Some(Background::Color(DESTRUCTIVE)),
+ border_radius: 3,
+ text_color: Color::WHITE,
+ ..button::Style::default()
+ }
+ }
+
+ fn hovered(&self) -> button::Style {
+ button::Style {
+ background: Some(Background::Color(Color {
+ a: 0.5,
+ ..DESTRUCTIVE
+ })),
+ text_color: Color::WHITE,
+ ..self.active()
+ }
+ }
+
+ fn pressed(&self) -> button::Style {
+ button::Style {
+ border_width: 1,
+ border_color: Color::WHITE,
+ ..self.hovered()
+ }
+ }
+}
+
pub struct Slider;
impl slider::StyleSheet for Slider {