Last active
March 19, 2019 21:15
-
-
Save zesterer/d1ac805193c955305d8ace8cf686ef07 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f32; | |
use minifb::{ | |
Key, | |
WindowOptions, | |
Window, | |
}; | |
use vek::*; | |
const W: usize = 64; | |
const H: usize = 64; | |
#[derive(Copy, Clone)] | |
struct Cell { | |
pop: f32, | |
vel: Vec2<f32>, | |
spread: f32, | |
solid: bool, | |
} | |
impl Cell { | |
pub fn empty() -> Self { | |
Cell { | |
pop: 0.0, | |
vel: Vec2::zero(), | |
spread: 0.8, | |
solid: false, | |
} | |
} | |
pub fn clean(&mut self) { | |
self.pop = 0.0; | |
} | |
#[inline(always)] | |
pub fn flow_factor(&self, vec: Option<Vec2<f32>>, other: &Self) -> f32 { | |
if other.solid { | |
0.0 | |
} else { | |
match vec { | |
Some(vec) => self.vel.dot(vec) + self.spread, | |
None => 1.0 / (1.0 + self.vel.magnitude() * 0.0), | |
} | |
} | |
} | |
pub fn tick(&self, (this, left, right, up, down): (&mut Self, &mut Self, &mut Self, &mut Self, &mut Self), delta: f32) { | |
let flow_factors = [ | |
self.flow_factor(None, this) / delta, | |
delta * self.flow_factor(Some(Vec2::left()), left), | |
delta * self.flow_factor(Some(Vec2::right()), right), | |
delta * self.flow_factor(Some(Vec2::up()), up), | |
delta * self.flow_factor(Some(Vec2::down()), down), | |
]; | |
let flow_sum: f32 = (&flow_factors).iter().sum::<f32>(); | |
let flow_vals = [ | |
self.pop * flow_factors[0] / flow_sum, | |
self.pop * flow_factors[1] / flow_sum, | |
self.pop * flow_factors[2] / flow_sum, | |
self.pop * flow_factors[3] / flow_sum, | |
self.pop * flow_factors[4] / flow_sum, | |
]; | |
//println!("Factors: {:?}", flow_factors); | |
this.pop += flow_vals[0]; | |
left.pop += flow_vals[1]; | |
right.pop += flow_vals[2]; | |
up.pop += flow_vals[3]; | |
down.pop += flow_vals[4]; | |
/* | |
left.vel += (self.vel + Vec3::left()) * flow_vals[1]; | |
this.vel -= (self.vel + Vec3::left()) * flow_vals[1]; | |
right.vel += (self.vel + Vec3::right()) * flow_vals[2]; | |
this.vel -= (self.vel + Vec3::right()) * flow_vals[2]; | |
up.vel += (self.vel + Vec3::up()) * flow_vals[3]; | |
this.vel -= (self.vel + Vec3::up()) * flow_vals[3]; | |
down.vel += (self.vel + Vec3::down()) * flow_vals[4]; | |
this.vel -= (self.vel + Vec3::down()) * flow_vals[4]; | |
*/ | |
} | |
pub fn get_colour(&self) -> u32 { | |
if self.solid { | |
0xFFFFFFFF | |
} else { | |
(self.pop as u32) << 16 | |
} | |
} | |
} | |
struct World { | |
cells: Box<[[Cell; H]; W]>, | |
} | |
impl World { | |
pub fn test() -> Self { | |
let mut this = Self { | |
cells: Box::new([[Cell::empty(); H]; W]), | |
}; | |
for i in 0..W { | |
for j in 0..H { | |
if | |
(i as i32 - W as i32 / 2).wrapping_pow(2) + | |
(j as i32 - H as i32 / 2).wrapping_pow(2) < 100 | |
{ | |
this.cells[i][j].pop = 250.0; | |
} | |
} | |
} | |
for i in 20..W - 20 { | |
this.cells[i][H / 3].solid = true; | |
} | |
this | |
} | |
pub fn tick(&mut self, delta: f32) { | |
let mut new_cells = self.cells.clone(); | |
for i in 0..W { | |
for j in 0..H { | |
new_cells[i][j].clean(); | |
} | |
} | |
for i in 1..W - 1 { | |
for j in 1..H - 1 { | |
let mut this = new_cells[i][j]; | |
let mut left = new_cells[i - 1][j]; | |
let mut right = new_cells[i + 1][j]; | |
let mut up = new_cells[i][j - 1]; | |
let mut down = new_cells[i][j + 1]; | |
self.cells[i][j].tick(( | |
&mut this, | |
&mut left, | |
&mut right, | |
&mut up, | |
&mut down, | |
), delta); | |
new_cells[i][j] = this; | |
new_cells[i - 1][j] = left; | |
new_cells[i + 1][j] = right; | |
new_cells[i][j - 1] = up; | |
new_cells[i][j + 1] = down; | |
} | |
} | |
self.cells = new_cells; | |
} | |
pub fn render_to(&self, buf: &mut [u32]) { | |
for i in 0..W { | |
for j in 0..H { | |
buf[j * W + i] = self.cells[i][j].get_colour(); | |
} | |
} | |
} | |
} | |
fn main() { | |
let mut buf = vec![0; W * H]; | |
let mut opts = WindowOptions::default(); | |
opts.scale = minifb::Scale::X4; | |
let mut win = Window::new("Worldsim", W, H, opts).unwrap(); | |
let mut world = World::test(); | |
while win.is_open() { | |
world.tick(0.1); | |
world.render_to(&mut buf); | |
win.update_with_buffer(&buf).unwrap(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment