diff --git a/src/bin/predprey/main.rs b/src/bin/predprey/main.rs index e0b986a..ed83642 100644 --- a/src/bin/predprey/main.rs +++ b/src/bin/predprey/main.rs @@ -9,8 +9,8 @@ use rand::thread_rng; use rand::Rng; use pixelfoo::color::Color; -use pixelfoo::p2; use pixelfoo::point2d::Point2d; +use pixelfoo::rect2d::Rect2d; use pixelfoo::vec2d::Vec2d; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -92,6 +92,8 @@ fn main() -> std::io::Result<()> { let t_frame = 0.040; // s let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32); + let board_rect = Rect2d::new(0, x_size as i32, 0, y_size as i32); + // mid point of the board let x_mid = (x_size - 1) as f64 / 2.0; let y_mid = (y_size - 1) as f64 / 2.0; @@ -101,11 +103,10 @@ fn main() -> std::io::Result<()> { loop { for _ in 0..arg { - let x = rng.gen_range(0, x_size); - let y = rng.gen_range(0, y_size); - let sq = board[y][x]; - let dx = (x as f64 - x_mid as f64) / r as f64; - let dy = (y as f64 - y_mid as f64) / r as f64; + let pos = board_rect.random_point(&mut rng); + let sq = board[pos.y as usize][pos.x as usize]; + let dx = (pos.x as f64 - x_mid as f64) / r as f64; + let dy = (pos.y as f64 - y_mid as f64) / r as f64; let p0 = (dx * dx + dy * dy).min(1.0); let p_survive = match sq { Square::Empty => 1.0, @@ -118,8 +119,7 @@ fn main() -> std::io::Result<()> { } else { Square::Empty }; - let pos = p2!(x as i32, y as i32); - board[y][x] = match sq { + board[pos.y as usize][pos.x as usize] = match sq { Square::Empty => grow(&board, pos, Square::Grass, new_sq), Square::Grass => grow(&board, pos, Square::Rabbit, new_sq), Square::Rabbit => grow(&board, pos, Square::Fox, new_sq), diff --git a/src/lib.rs b/src/lib.rs index 7d91fa8..2a5189d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ pub mod color; -#[macro_use] -pub mod point2d; + #[macro_use] pub mod vec2d; + +#[macro_use] +pub mod point2d; + +pub mod rect2d; diff --git a/src/rect2d.rs b/src/rect2d.rs index 0a1db40..610e10a 100644 --- a/src/rect2d.rs +++ b/src/rect2d.rs @@ -1,4 +1,54 @@ +use rand::Rng; + +use crate::p2; +use crate::point2d::Point2d; +use crate::v2; +use crate::vec2d::Vec2d; + pub struct Rect2d { origin: Point2d, size: Vec2d, } + +impl Rect2d { + pub fn new(x0: i32, x1: i32, y0: i32, y1: i32) -> Rect2d { + assert!(x0 <= x1 && y0 <= y1); + let origin = p2!(x0, y0); + let size = v2!(x1 - x0, y1 - y0); + Rect2d { origin, size } + } + + pub fn left(&self) -> i32 { + self.origin.x + } + pub fn right(&self) -> i32 { + self.origin.x + self.size.x + } + + pub fn bottom(&self) -> i32 { + self.origin.y + } + pub fn top(&self) -> i32 { + self.origin.y + self.size.y + } + + pub fn width(&self) -> i32 { + self.size.x + } + pub fn height(&self) -> i32 { + self.size.y + } + + pub fn contains(&self, p: Point2d) -> bool { + self.left() <= p.x && p.x < self.right() && self.bottom() <= p.y && p.y < self.top() + } + + pub fn random_point(&self, rng: &mut R) -> Point2d + where + R: Rng, + { + let x = rng.gen_range(self.left(), self.right()); + let y = rng.gen_range(self.bottom(), self.top()); + p2!(x, y) + } +}