diff --git a/src/lib.rs b/src/lib.rs index e69de29..501db3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,58 @@ +use sdl2::render::Canvas; +use sdl2::pixels::Color; +use sdl2::video::Window; +use sdl2::rect::Rect; + + +use std::cmp; + +pub mod life; + +pub const BLACK: Color = Color::RGB(0, 0, 0); +pub const WHITE: Color = Color::RGB(255, 255, 255); + + + +#[derive(Clone)] +pub struct Cell { + pub color: Color, +} + +pub trait Engine { + fn evolve(&mut self) -> Vec>; +} + +pub struct Renderer { + pub px_size: i32, + pub canvas: Canvas, +} + +impl Renderer { + pub fn new(px_size: i32, canvas: Canvas) -> Renderer { + Renderer { px_size: px_size, canvas: canvas } + } + + pub fn render(&mut self, grid: &Vec>) { + self.canvas.set_draw_color(BLACK); + self.canvas.clear(); + + for y in 0..grid.len() { + for x in 0..grid[y].len() { + //if grid[y][x].alive { + self.canvas.set_draw_color(grid[y][x].color); + self.canvas.fill_rect(Rect::new(x as i32 * self.px_size, y as i32 * self.px_size, self.px_size as u32, self.px_size as u32)); + //} + } + } + + /* + for (y, row) in grid.iter().enumerate() { + for (x, cell) in row.iter().enumerate() { + rectangle( cell.color, rectangle::square((x as u32 * px_size) as f64, (y as u32 * px_size) as f64, px_size as f64), c.transform, gl) + } + }*/ + + + self.canvas.present(); + } +} \ No newline at end of file diff --git a/src/life.rs b/src/life.rs new file mode 100644 index 0000000..a6efca6 --- /dev/null +++ b/src/life.rs @@ -0,0 +1,75 @@ +use std::cmp; + +use super::{Cell, Engine, WHITE, BLACK}; + +pub struct LifeEngine { + grid: Vec>, +} + + +pub fn new(size: usize) -> LifeEngine { + let mut life = LifeEngine{grid: vec![vec![false; size]; size]}; + + // r pemento + let centery = size/2; + let centerx = size/2; + + life.grid[centery][centerx] = true; + life.grid[centery+1][centerx] = true; + life.grid[centery-1][centerx] = true; + + life.grid[centery-1][centerx-1] = true; + life.grid[centery][centerx+1] = true; + + life +} + + +impl Engine for LifeEngine { + fn evolve(&mut self) -> Vec> { + let mut new_render_grid = vec![vec![Cell{color: BLACK}; self.grid.len()]; self.grid.len()]; + let mut new_life_grid = vec![vec![false; self.grid.len()]; self.grid.len()]; + + for y in 0..self.grid.len() { + for x in 0..self.grid[y].len() { + let mut nalive = 0; + + let mut ylow = 0; + if y > 1 { + ylow = y-1; + } + let yhigh = cmp::min(self.grid.len()-1, y+1); + + let mut xlow = 0; + if x > 1 { + xlow = x-1; + } + let xhigh = cmp::min(self.grid.len()-1, x+1); + + for i in ylow..yhigh+1 { + for j in xlow..xhigh+1 { + if i == y && j == x { + continue; + } + if self.grid[i][j] { + nalive += 1; + } + } + } + + if self.grid[y][x] { + if nalive == 2 || nalive == 3 { + new_render_grid[y][x] = Cell{color: WHITE}; + new_life_grid[y][x] = true; + } + } else if nalive == 3 { + new_render_grid[y][x] = Cell{color: WHITE}; + new_life_grid[y][x] = true; + } + } + } + + self.grid = new_life_grid; + new_render_grid + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8ecff9b..f321eb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,134 +1,26 @@ - use sdl2::render::Canvas; -use sdl2::pixels::Color; use sdl2::video::Window; -use sdl2::rect::Rect; - -use std::cmp; use std::{thread, time}; -use std::time::{Duration, SystemTime}; +use std::time::{SystemTime}; + +use microworlds::Engine; pub const SCREEN_SIZE: u32 = 800; pub const PX_SIZE: u32 = 2; -pub const BLACK: Color = Color::RGB(0, 0, 0); -pub const WHITE: Color = Color::RGB(255, 255, 255); - -pub trait Cell { - fn color(&self) -> [f32; 4]; -} - -#[derive(Clone)] -pub struct ConwayCell { - color: Color, - alive: bool, -} - -/* -impl Cell { - pub fn clone(&self) -> Cell { - Cell{color: self.color} - } -}*/ - -pub struct App { - steps_per_sec: u64, - px_size: i32, - grid: Vec>, - canvas: Canvas, -} - -impl App { - fn render (&mut self) { - - self.canvas.set_draw_color(Color::RGB(0, 0, 0)); - self.canvas.clear(); - - for y in 0..self.grid.len() { - for x in 0..self.grid[y].len() { - if self.grid[y][x].alive { - self.canvas.set_draw_color(self.grid[y][x].color); - self.canvas.fill_rect(Rect::new(x as i32 * self.px_size , y as i32 * self.px_size, self.px_size as u32, self.px_size as u32)); - } - } - } - - /* - for (y, row) in grid.iter().enumerate() { - for (x, cell) in row.iter().enumerate() { - rectangle( cell.color, rectangle::square((x as u32 * px_size) as f64, (y as u32 * px_size) as f64, px_size as f64), c.transform, gl) - } - }*/ - - - self.canvas.present(); - } - - - fn evolve(&mut self) { - let mut new_grid = vec![vec![ConwayCell{color: BLACK, alive: false}; self.grid.len()]; self.grid.len()]; - - for y in 0..self.grid.len() { - for x in 0..self.grid[y].len() { - let mut nalive = 0; - - let mut ylow = 0; - if y > 1 { - ylow = y-1; - } - let yhigh = cmp::min(self.grid.len()-1, y+1); - - let mut xlow = 0; - if x > 1 { - xlow = x-1; - } - let xhigh = cmp::min(self.grid.len()-1, x+1); - - for i in ylow..yhigh+1 { - for j in xlow..xhigh+1 { - if i == y && j == x { - continue; - } - if self.grid[i][j].alive { - nalive += 1; - } - } - } - - if self.grid[y][x].alive { - if nalive == 2 || nalive == 3 { - new_grid[y][x] = ConwayCell{color: WHITE, alive: true} - } - } else if nalive == 3 { - new_grid[y][x] = ConwayCell{color: WHITE, alive: true} - } - } - } - self.grid = new_grid; - } -} +pub const STEPS_PER_SEC: u64 = 8; fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); let window = video_subsystem.window("Microworlds", SCREEN_SIZE, SCREEN_SIZE).build().unwrap(); - - - + println!("Window: {}x{} at {} px per cell", SCREEN_SIZE, SCREEN_SIZE, PX_SIZE); let size: usize = (SCREEN_SIZE/PX_SIZE) as usize; - let mut grid = vec![vec![ConwayCell{color: BLACK, alive: false}; size]; size]; - println!("size:{}", size); + let mut grid = vec![vec![microworlds::Cell{color: microworlds::BLACK}; size]; size]; - // r pemento - let centery = size/2; - let centerx = size/2; - println!("centery:{} centerx:{}", centery, centerx); - grid[centery][centerx] = ConwayCell{color: WHITE, alive: true}; - grid[centery+1][centerx] = ConwayCell{color: WHITE, alive: true}; - grid[centery-1][centerx] = ConwayCell{color: WHITE, alive: true}; + println!("cell grid: {}x{} ({} cells) - {} steps per sec", size, size, (size*size), STEPS_PER_SEC); - grid[centery-1][centerx-1] = ConwayCell{color: WHITE, alive: true}; - grid[centery][centerx+1] = ConwayCell{color: WHITE, alive: true}; + let mut engine = microworlds::life::new(size); // Let's create a Canvas which we will use to draw in our Window let canvas : Canvas = window.into_canvas() @@ -136,17 +28,13 @@ fn main() { // render faster than your display rate (usually 60Hz or 144Hz) .build().unwrap(); - let mut app = App { - steps_per_sec: 32, - px_size: PX_SIZE as i32, - grid: grid, - canvas: canvas, - }; - + let mut renderer= microworlds::Renderer::new( PX_SIZE as i32, canvas); let mut frame = 0; let mut event_pump = sdl_context.event_pump().unwrap(); + + let period = time::Duration::from_millis(1000 / STEPS_PER_SEC); 'main: loop { for event in event_pump.poll_iter() { match event { @@ -156,16 +44,17 @@ fn main() { } let start_rend = SystemTime::now(); - app.render(); + renderer.render(&grid); let render_time = start_rend.elapsed().unwrap(); let start_evo = SystemTime::now(); - app.evolve(); + grid = engine.evolve(); let evo_time = start_evo.elapsed().unwrap(); let total_time = start_rend.elapsed().unwrap(); frame += 1; println!("frame: {} - render time: {:?} | evolve time: {:?} | total time: {:?}", frame, render_time, evo_time, total_time); - thread::sleep(time::Duration::from_millis(1000 / app.steps_per_sec)); + if total_time < period { + thread::sleep(period - total_time); + } } - }