Skip to content

Instantly share code, notes, and snippets.

@zesterer
Last active March 19, 2019 21:15
Show Gist options
  • Save zesterer/d1ac805193c955305d8ace8cf686ef07 to your computer and use it in GitHub Desktop.
Save zesterer/d1ac805193c955305d8ace8cf686ef07 to your computer and use it in GitHub Desktop.
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