Simplify logic and limit ticks in game_of_life
This commit is contained in:
parent
0025b8c3f8
commit
cc8f5b6fc8
1 changed files with 34 additions and 74 deletions
|
|
@ -19,26 +19,16 @@ pub fn main() {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct GameOfLife {
|
struct GameOfLife {
|
||||||
grid: Grid,
|
grid: Grid,
|
||||||
state: State,
|
is_playing: bool,
|
||||||
speed: u64,
|
speed: usize,
|
||||||
next_speed: Option<u64>,
|
next_speed: Option<usize>,
|
||||||
toggle_button: button::State,
|
toggle_button: button::State,
|
||||||
next_button: button::State,
|
next_button: button::State,
|
||||||
clear_button: button::State,
|
clear_button: button::State,
|
||||||
speed_slider: slider::State,
|
speed_slider: slider::State,
|
||||||
tick_duration: Duration,
|
tick_duration: Duration,
|
||||||
tick_amount: usize,
|
queued_ticks: usize,
|
||||||
}
|
last_ticks: usize,
|
||||||
|
|
||||||
enum State {
|
|
||||||
Paused,
|
|
||||||
Playing { last_tick: Instant },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for State {
|
|
||||||
fn default() -> State {
|
|
||||||
State::Paused
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -73,68 +63,48 @@ impl Application for GameOfLife {
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Grid(message) => {
|
Message::Grid(message) => {
|
||||||
if let Some((tick_duration, tick_amount)) =
|
if let Some(tick_duration) = self.grid.update(message) {
|
||||||
self.grid.update(message)
|
|
||||||
{
|
|
||||||
self.tick_duration = tick_duration;
|
self.tick_duration = tick_duration;
|
||||||
self.tick_amount = tick_amount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Tick(_) | Message::Next => match &mut self.state {
|
Message::Tick(_) | Message::Next => {
|
||||||
State::Paused => {
|
if let Some(task) = self.grid.tick(self.queued_ticks + 1) {
|
||||||
if let Some(task) = self.grid.tick(1) {
|
self.last_ticks = self.queued_ticks;
|
||||||
return Command::perform(task, Message::Grid);
|
self.queued_ticks = 0;
|
||||||
|
|
||||||
|
if let Some(speed) = self.next_speed.take() {
|
||||||
|
self.speed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Command::perform(task, Message::Grid);
|
||||||
|
} else {
|
||||||
|
self.queued_ticks = (self.queued_ticks + 1).min(self.speed);
|
||||||
}
|
}
|
||||||
State::Playing { last_tick } => {
|
}
|
||||||
let seconds_elapsed =
|
|
||||||
last_tick.elapsed().as_millis() as f32 / 1000.0;
|
|
||||||
|
|
||||||
let needed_ticks =
|
|
||||||
(self.speed as f32 * seconds_elapsed).ceil() as usize;
|
|
||||||
|
|
||||||
if let Some(task) = self.grid.tick(needed_ticks.max(1)) {
|
|
||||||
*last_tick = Instant::now();
|
|
||||||
|
|
||||||
if let Some(speed) = self.next_speed.take() {
|
|
||||||
self.speed = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Command::perform(task, Message::Grid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Message::Toggle => {
|
Message::Toggle => {
|
||||||
self.state = match self.state {
|
self.is_playing = !self.is_playing;
|
||||||
State::Paused => State::Playing {
|
|
||||||
last_tick: Instant::now(),
|
|
||||||
},
|
|
||||||
State::Playing { .. } => State::Paused,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Message::Clear => {
|
Message::Clear => {
|
||||||
self.grid.clear();
|
self.grid.clear();
|
||||||
}
|
}
|
||||||
Message::SpeedChanged(speed) => match self.state {
|
Message::SpeedChanged(speed) => {
|
||||||
State::Paused => {
|
if self.is_playing {
|
||||||
self.speed = speed.round() as u64;
|
self.next_speed = Some(speed.round() as usize);
|
||||||
|
} else {
|
||||||
|
self.speed = speed.round() as usize;
|
||||||
}
|
}
|
||||||
State::Playing { .. } => {
|
}
|
||||||
self.next_speed = Some(speed.round() as u64);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
match self.state {
|
if self.is_playing {
|
||||||
State::Paused => Subscription::none(),
|
time::every(Duration::from_millis(1000 / self.speed as u64))
|
||||||
State::Playing { .. } => {
|
.map(Message::Tick)
|
||||||
time::every(Duration::from_millis(1000 / self.speed))
|
} else {
|
||||||
.map(Message::Tick)
|
Subscription::none()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,11 +114,7 @@ impl Application for GameOfLife {
|
||||||
.push(
|
.push(
|
||||||
Button::new(
|
Button::new(
|
||||||
&mut self.toggle_button,
|
&mut self.toggle_button,
|
||||||
Text::new(if let State::Paused = self.state {
|
Text::new(if self.is_playing { "Pause" } else { "Play" }),
|
||||||
"Play"
|
|
||||||
} else {
|
|
||||||
"Pause"
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.on_press(Message::Toggle)
|
.on_press(Message::Toggle)
|
||||||
.style(style::Button),
|
.style(style::Button),
|
||||||
|
|
@ -185,7 +151,7 @@ impl Application for GameOfLife {
|
||||||
.push(
|
.push(
|
||||||
Text::new(format!(
|
Text::new(format!(
|
||||||
"{:?} ({})",
|
"{:?} ({})",
|
||||||
self.tick_duration, self.tick_amount
|
self.tick_duration, self.last_ticks
|
||||||
))
|
))
|
||||||
.size(14),
|
.size(14),
|
||||||
);
|
);
|
||||||
|
|
@ -239,7 +205,6 @@ mod grid {
|
||||||
Ticked {
|
Ticked {
|
||||||
result: Result<Life, TickError>,
|
result: Result<Life, TickError>,
|
||||||
tick_duration: Duration,
|
tick_duration: Duration,
|
||||||
tick_amount: usize,
|
|
||||||
version: usize,
|
version: usize,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +251,6 @@ mod grid {
|
||||||
result,
|
result,
|
||||||
version,
|
version,
|
||||||
tick_duration,
|
tick_duration,
|
||||||
tick_amount: amount,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -298,10 +262,7 @@ mod grid {
|
||||||
self.cache.clear();
|
self.cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(
|
pub fn update(&mut self, message: Message) -> Option<Duration> {
|
||||||
&mut self,
|
|
||||||
message: Message,
|
|
||||||
) -> Option<(Duration, usize)> {
|
|
||||||
match message {
|
match message {
|
||||||
Message::Populate(cell) => {
|
Message::Populate(cell) => {
|
||||||
self.state.populate(cell);
|
self.state.populate(cell);
|
||||||
|
|
@ -313,12 +274,11 @@ mod grid {
|
||||||
result: Ok(life),
|
result: Ok(life),
|
||||||
version,
|
version,
|
||||||
tick_duration,
|
tick_duration,
|
||||||
tick_amount,
|
|
||||||
} if version == self.version => {
|
} if version == self.version => {
|
||||||
self.state.update(life);
|
self.state.update(life);
|
||||||
self.cache.clear();
|
self.cache.clear();
|
||||||
|
|
||||||
Some((tick_duration, tick_amount))
|
Some(tick_duration)
|
||||||
}
|
}
|
||||||
Message::Ticked {
|
Message::Ticked {
|
||||||
result: Err(error), ..
|
result: Err(error), ..
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue