refactor engine and renderer, now life is a drop in engine
This commit is contained in:
parent
4da6c7caa6
commit
6381d02fb9
58
src/lib.rs
58
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<Vec<Cell>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Renderer {
|
||||||
|
pub px_size: i32,
|
||||||
|
pub canvas: Canvas<Window>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn new(px_size: i32, canvas: Canvas<Window>) -> Renderer {
|
||||||
|
Renderer { px_size: px_size, canvas: canvas }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&mut self, grid: &Vec<Vec<Cell>>) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
use super::{Cell, Engine, WHITE, BLACK};
|
||||||
|
|
||||||
|
pub struct LifeEngine {
|
||||||
|
grid: Vec<Vec<bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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<Vec<Cell>> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
143
src/main.rs
143
src/main.rs
|
@ -1,134 +1,26 @@
|
||||||
|
|
||||||
use sdl2::render::Canvas;
|
use sdl2::render::Canvas;
|
||||||
use sdl2::pixels::Color;
|
|
||||||
use sdl2::video::Window;
|
use sdl2::video::Window;
|
||||||
use sdl2::rect::Rect;
|
|
||||||
|
|
||||||
|
|
||||||
use std::cmp;
|
|
||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{SystemTime};
|
||||||
|
|
||||||
|
use microworlds::Engine;
|
||||||
|
|
||||||
pub const SCREEN_SIZE: u32 = 800;
|
pub const SCREEN_SIZE: u32 = 800;
|
||||||
pub const PX_SIZE: u32 = 2;
|
pub const PX_SIZE: u32 = 2;
|
||||||
pub const BLACK: Color = Color::RGB(0, 0, 0);
|
pub const STEPS_PER_SEC: u64 = 8;
|
||||||
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<Vec<ConwayCell>>,
|
|
||||||
canvas: Canvas<Window>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
let window = video_subsystem.window("Microworlds", SCREEN_SIZE, SCREEN_SIZE).build().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 size: usize = (SCREEN_SIZE/PX_SIZE) as usize;
|
||||||
let mut grid = vec![vec![ConwayCell{color: BLACK, alive: false}; size]; size];
|
let mut grid = vec![vec![microworlds::Cell{color: microworlds::BLACK}; size]; size];
|
||||||
println!("size:{}", size);
|
|
||||||
|
|
||||||
// r pemento
|
println!("cell grid: {}x{} ({} cells) - {} steps per sec", size, size, (size*size), STEPS_PER_SEC);
|
||||||
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};
|
|
||||||
|
|
||||||
grid[centery-1][centerx-1] = ConwayCell{color: WHITE, alive: true};
|
let mut engine = microworlds::life::new(size);
|
||||||
grid[centery][centerx+1] = ConwayCell{color: WHITE, alive: true};
|
|
||||||
|
|
||||||
// Let's create a Canvas which we will use to draw in our Window
|
// Let's create a Canvas which we will use to draw in our Window
|
||||||
let canvas : Canvas<Window> = window.into_canvas()
|
let canvas : Canvas<Window> = window.into_canvas()
|
||||||
|
@ -136,17 +28,13 @@ fn main() {
|
||||||
// render faster than your display rate (usually 60Hz or 144Hz)
|
// render faster than your display rate (usually 60Hz or 144Hz)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
let mut app = App {
|
let mut renderer= microworlds::Renderer::new( PX_SIZE as i32, canvas);
|
||||||
steps_per_sec: 32,
|
|
||||||
px_size: PX_SIZE as i32,
|
|
||||||
grid: grid,
|
|
||||||
canvas: canvas,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let mut frame = 0;
|
let mut frame = 0;
|
||||||
|
|
||||||
let mut event_pump = sdl_context.event_pump().unwrap();
|
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||||
|
|
||||||
|
let period = time::Duration::from_millis(1000 / STEPS_PER_SEC);
|
||||||
'main: loop {
|
'main: loop {
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
|
@ -156,16 +44,17 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_rend = SystemTime::now();
|
let start_rend = SystemTime::now();
|
||||||
app.render();
|
renderer.render(&grid);
|
||||||
let render_time = start_rend.elapsed().unwrap();
|
let render_time = start_rend.elapsed().unwrap();
|
||||||
let start_evo = SystemTime::now();
|
let start_evo = SystemTime::now();
|
||||||
app.evolve();
|
grid = engine.evolve();
|
||||||
let evo_time = start_evo.elapsed().unwrap();
|
let evo_time = start_evo.elapsed().unwrap();
|
||||||
let total_time = start_rend.elapsed().unwrap();
|
let total_time = start_rend.elapsed().unwrap();
|
||||||
frame += 1;
|
frame += 1;
|
||||||
println!("frame: {} - render time: {:?} | evolve time: {:?} | total time: {:?}", frame, render_time, evo_time, total_time);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue