microworlds-rs/src/main.rs

172 lines
4.9 KiB
Rust

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};
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<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() {
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();
let size: usize = (SCREEN_SIZE/PX_SIZE) as usize;
let mut grid = vec![vec![ConwayCell{color: BLACK, alive: false}; size]; size];
println!("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};
grid[centery-1][centerx-1] = ConwayCell{color: WHITE, alive: true};
grid[centery][centerx+1] = ConwayCell{color: WHITE, alive: true};
// Let's create a Canvas which we will use to draw in our Window
let canvas : Canvas<Window> = window.into_canvas()
.present_vsync() //< this means the screen cannot
// 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 frame = 0;
let mut event_pump = sdl_context.event_pump().unwrap();
'main: loop {
for event in event_pump.poll_iter() {
match event {
sdl2::event::Event::Quit {..} => break 'main,
_ => {},
}
}
let start_rend = SystemTime::now();
app.render();
let render_time = start_rend.elapsed().unwrap();
let start_evo = SystemTime::now();
app.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));
}
}