Draw grid in game_of_life
This commit is contained in:
parent
a43fb42428
commit
c3c5161386
1 changed files with 73 additions and 18 deletions
|
|
@ -13,7 +13,10 @@ use iced::{
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
GameOfLife::run(Settings::default())
|
GameOfLife::run(Settings {
|
||||||
|
antialiasing: true,
|
||||||
|
..Settings::default()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -132,12 +135,14 @@ mod grid {
|
||||||
};
|
};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::ops::RangeInclusive;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub struct Grid {
|
pub struct Grid {
|
||||||
state: State,
|
state: State,
|
||||||
interaction: Interaction,
|
interaction: Interaction,
|
||||||
cache: Cache,
|
life_cache: Cache,
|
||||||
|
grid_cache: Cache,
|
||||||
translation: Vector,
|
translation: Vector,
|
||||||
scaling: f32,
|
scaling: f32,
|
||||||
version: usize,
|
version: usize,
|
||||||
|
|
@ -163,7 +168,8 @@ mod grid {
|
||||||
Self {
|
Self {
|
||||||
state: State::default(),
|
state: State::default(),
|
||||||
interaction: Interaction::None,
|
interaction: Interaction::None,
|
||||||
cache: Cache::default(),
|
life_cache: Cache::default(),
|
||||||
|
grid_cache: Cache::default(),
|
||||||
translation: Vector::default(),
|
translation: Vector::default(),
|
||||||
scaling: 1.0,
|
scaling: 1.0,
|
||||||
version: 0,
|
version: 0,
|
||||||
|
|
@ -203,14 +209,14 @@ mod grid {
|
||||||
self.state = State::default();
|
self.state = State::default();
|
||||||
self.version += 1;
|
self.version += 1;
|
||||||
|
|
||||||
self.cache.clear();
|
self.life_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, message: Message) -> Option<Duration> {
|
pub fn update(&mut self, message: Message) -> Option<Duration> {
|
||||||
match message {
|
match message {
|
||||||
Message::Populate(cell) => {
|
Message::Populate(cell) => {
|
||||||
self.state.populate(cell);
|
self.state.populate(cell);
|
||||||
self.cache.clear();
|
self.life_cache.clear();
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +226,7 @@ mod grid {
|
||||||
tick_duration,
|
tick_duration,
|
||||||
} if version == self.version => {
|
} if version == self.version => {
|
||||||
self.state.update(life);
|
self.state.update(life);
|
||||||
self.cache.clear();
|
self.life_cache.clear();
|
||||||
|
|
||||||
Some(tick_duration)
|
Some(tick_duration)
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +316,8 @@ mod grid {
|
||||||
+ (cursor_position - start)
|
+ (cursor_position - start)
|
||||||
* (1.0 / self.scaling);
|
* (1.0 / self.scaling);
|
||||||
|
|
||||||
self.cache.clear();
|
self.life_cache.clear();
|
||||||
|
self.grid_cache.clear();
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +351,8 @@ mod grid {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cache.clear();
|
self.life_cache.clear();
|
||||||
|
self.grid_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|
@ -358,7 +366,7 @@ mod grid {
|
||||||
fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> {
|
fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> {
|
||||||
let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0);
|
let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0);
|
||||||
|
|
||||||
let life = self.cache.draw(bounds.size(), |frame| {
|
let life = self.life_cache.draw(bounds.size(), |frame| {
|
||||||
let background = Path::rectangle(Point::ORIGIN, frame.size());
|
let background = Path::rectangle(Point::ORIGIN, frame.size());
|
||||||
frame.fill(&background, Color::from_rgb8(0x40, 0x44, 0x4B));
|
frame.fill(&background, Color::from_rgb8(0x40, 0x44, 0x4B));
|
||||||
|
|
||||||
|
|
@ -370,7 +378,7 @@ mod grid {
|
||||||
|
|
||||||
let region = self.visible_region(frame.size());
|
let region = self.visible_region(frame.size());
|
||||||
|
|
||||||
for cell in region.view(self.state.cells()) {
|
for cell in region.cull(self.state.cells()) {
|
||||||
frame.fill_rectangle(
|
frame.fill_rectangle(
|
||||||
Point::new(cell.j as f32, cell.i as f32),
|
Point::new(cell.j as f32, cell.i as f32),
|
||||||
Size::UNIT,
|
Size::UNIT,
|
||||||
|
|
@ -405,7 +413,44 @@ mod grid {
|
||||||
frame.into_geometry()
|
frame.into_geometry()
|
||||||
};
|
};
|
||||||
|
|
||||||
vec![life, hovered_cell]
|
if self.scaling < 0.2 {
|
||||||
|
vec![life, hovered_cell]
|
||||||
|
} else {
|
||||||
|
let grid = self.grid_cache.draw(bounds.size(), |frame| {
|
||||||
|
frame.translate(center);
|
||||||
|
frame.scale(self.scaling);
|
||||||
|
frame.translate(self.translation);
|
||||||
|
frame.scale(Cell::SIZE as f32);
|
||||||
|
|
||||||
|
let region = self.visible_region(frame.size());
|
||||||
|
let rows = region.rows();
|
||||||
|
let columns = region.columns();
|
||||||
|
let (total_rows, total_columns) =
|
||||||
|
(rows.clone().count(), columns.clone().count());
|
||||||
|
let width = 2.0 / Cell::SIZE as f32;
|
||||||
|
let color = Color::from_rgb8(70, 74, 83);
|
||||||
|
|
||||||
|
frame.translate(Vector::new(-width / 2.0, -width / 2.0));
|
||||||
|
|
||||||
|
for row in region.rows() {
|
||||||
|
frame.fill_rectangle(
|
||||||
|
Point::new(*columns.start() as f32, row as f32),
|
||||||
|
Size::new(total_columns as f32, width),
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for column in region.columns() {
|
||||||
|
frame.fill_rectangle(
|
||||||
|
Point::new(column as f32, *rows.start() as f32),
|
||||||
|
Size::new(width, total_rows as f32),
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
vec![life, grid, hovered_cell]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_interaction(
|
fn mouse_interaction(
|
||||||
|
|
@ -583,20 +628,30 @@ mod grid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region {
|
impl Region {
|
||||||
fn view<'a>(
|
fn rows(&self) -> RangeInclusive<isize> {
|
||||||
&self,
|
|
||||||
cells: impl Iterator<Item = &'a Cell>,
|
|
||||||
) -> impl Iterator<Item = &'a Cell> {
|
|
||||||
let first_row = (self.y / Cell::SIZE as f32).floor() as isize;
|
let first_row = (self.y / Cell::SIZE as f32).floor() as isize;
|
||||||
let first_column = (self.x / Cell::SIZE as f32).floor() as isize;
|
|
||||||
|
|
||||||
let visible_rows =
|
let visible_rows =
|
||||||
(self.height / Cell::SIZE as f32).ceil() as isize;
|
(self.height / Cell::SIZE as f32).ceil() as isize;
|
||||||
|
|
||||||
|
first_row..=first_row + visible_rows
|
||||||
|
}
|
||||||
|
|
||||||
|
fn columns(&self) -> RangeInclusive<isize> {
|
||||||
|
let first_column = (self.x / Cell::SIZE as f32).floor() as isize;
|
||||||
|
|
||||||
let visible_columns =
|
let visible_columns =
|
||||||
(self.width / Cell::SIZE as f32).ceil() as isize;
|
(self.width / Cell::SIZE as f32).ceil() as isize;
|
||||||
|
|
||||||
let rows = first_row..=first_row + visible_rows;
|
first_column..=first_column + visible_columns
|
||||||
let columns = first_column..=first_column + visible_columns;
|
}
|
||||||
|
|
||||||
|
fn cull<'a>(
|
||||||
|
&self,
|
||||||
|
cells: impl Iterator<Item = &'a Cell>,
|
||||||
|
) -> impl Iterator<Item = &'a Cell> {
|
||||||
|
let rows = self.rows();
|
||||||
|
let columns = self.columns();
|
||||||
|
|
||||||
cells.filter(move |cell| {
|
cells.filter(move |cell| {
|
||||||
rows.contains(&cell.i) && columns.contains(&cell.j)
|
rows.contains(&cell.i) && columns.contains(&cell.j)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue