summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorMalte Voos <git@mal.tc>2023-04-02 12:24:23 +0200
committerMalte Voos <git@mal.tc>2023-04-02 12:24:23 +0200
commit58b1fced2563f40990123ab362b0df53b5a91c0e (patch)
tree84faaa57a23633041baffe5d50467e60abc9d5e9 /src/main.rs
parent7d9836ebef1950c550081b2ea9cd3f7718280a02 (diff)
downloadlife-58b1fced2563f40990123ab362b0df53b5a91c0e.tar.gz
life-58b1fced2563f40990123ab362b0df53b5a91c0e.zip
make it run in the browser
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs233
1 files changed, 0 insertions, 233 deletions
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index a9af30d..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,233 +0,0 @@
-use pixels::wgpu::Color;
-use pixels::PixelsBuilder;
-use pixels::SurfaceTexture;
-use rand::distributions::Standard;
-use rand::prelude::Distribution;
-use winit::dpi::PhysicalSize;
-use winit::event::Event;
-use winit::event_loop::EventLoop;
-use winit::window::WindowBuilder;
-use winit_input_helper::WinitInputHelper;
-
-const RES_X: usize = 265;
-const RES_Y: usize = 265;
-
-const WIN_WIDTH: u32 = 4 * RES_X as u32;
-const WIN_HEIGHT: u32 = 4 * RES_Y as u32;
-
-fn main() -> anyhow::Result<()> {
- let event_loop = EventLoop::new();
- let window = WindowBuilder::new()
- .with_inner_size(PhysicalSize {
- width: WIN_WIDTH,
- height: WIN_HEIGHT,
- })
- .with_resizable(false)
- .build(&event_loop)?;
- let mut input = WinitInputHelper::new();
-
- let window_size = window.inner_size();
- let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
-
- let mut pixels = PixelsBuilder::new(RES_X as u32, RES_Y as u32, surface_texture)
- .clear_color(Color {
- r: 0.0,
- g: 0.0,
- b: 0.0,
- a: 1.0,
- })
- .build()?;
- let mut life = Life::new();
-
- event_loop.run(move |event, _, control_flow| {
- control_flow.set_poll();
-
- if let Event::RedrawRequested(_) = event {
- life.draw(pixels.get_frame());
- pixels.render().expect("failed to render");
- }
-
- if input.update(&event) {
- if input.quit() {
- control_flow.set_exit();
- return;
- };
-
- life.update();
- window.request_redraw();
- };
- });
-}
-
-#[derive(Clone, Copy, Debug)]
-enum Cell {
- Alive,
- Dead { since: u8 },
-}
-
-#[derive(Debug)]
-struct Grid {
- pub cells: [[Cell; RES_X]; RES_Y],
-}
-
-enum FrontGrid {
- A,
- B,
-}
-
-struct Life {
- grid_a: Grid,
- grid_b: Grid,
- front_grid: FrontGrid,
-}
-
-impl Cell {
- pub fn is_alive(&self) -> bool {
- match self {
- Cell::Alive => true,
- Cell::Dead { .. } => false,
- }
- }
-}
-
-impl Grid {
- pub fn blank() -> Self {
- Self {
- cells: [[Cell::Dead { since: 0xff }; RES_X]; RES_Y],
- }
- }
-
- pub fn with_random_borders() -> Self {
- let mut ret = Self::blank();
- ret.randomize_border();
- ret
- }
-
- pub fn randomize_border(&mut self) {
- self.cells[RES_X - 1] = rand::random();
- }
-
- pub fn draw(&self, frame: &mut [u8]) {
- for row in 0..RES_X {
- for col in 0..RES_Y {
- let pixel_idx = 4 * (RES_X * row + col);
-
- match self.cells[row][col] {
- Cell::Alive => {
- frame[pixel_idx + 0] = 0xff; // R
- frame[pixel_idx + 1] = 0xff; // G
- frame[pixel_idx + 2] = 0xff; // B
- frame[pixel_idx + 3] = 0xff; // A
- }
- Cell::Dead { since } => {
- frame[pixel_idx + 0] = 0xff - since.saturating_mul(16); // R
- frame[pixel_idx + 1] = if since < 0x8 {
- 0
- } else {
- (since - 0x8).saturating_mul(0x8) / 2
- };
- // G
- frame[pixel_idx + 2] = 0xff; // B
- frame[pixel_idx + 3] = 0xff - since; // A
- }
- };
- }
- }
- }
-
- pub fn num_alive_neighbors(&self, row: usize, col: usize) -> u8 {
- let mut ret = 0;
-
- for i in row.saturating_sub(1)..=(row + 1).min(RES_X - 1) {
- for j in col.saturating_sub(1)..=(col + 1).min(RES_Y - 1) {
- if self.cells[i][j].is_alive() {
- ret += 1;
- }
- }
- }
- if self.cells[row][col].is_alive() {
- ret -= 1;
- }
-
- ret
- }
-
- pub fn new_state(&self, row: usize, col: usize) -> Cell {
- match self.cells[row][col] {
- Cell::Alive => {
- if (2..=3).contains(&self.num_alive_neighbors(row, col)) {
- Cell::Alive
- } else {
- Cell::Dead { since: 0 }
- }
- }
- Cell::Dead { since } => {
- if self.num_alive_neighbors(row, col) == 3 {
- Cell::Alive
- } else {
- Cell::Dead {
- since: since.saturating_add(1),
- }
- }
- }
- }
- }
-}
-
-impl Life {
- pub fn new() -> Self {
- Life {
- grid_a: Grid::with_random_borders(),
- grid_b: Grid::blank(),
- front_grid: FrontGrid::A,
- }
- }
-
- pub fn draw(&self, frame: &mut [u8]) {
- self.front_grid().draw(frame);
- }
-
- pub fn update(&mut self) {
- let (front, back) = self.grids();
-
- for row in 0..RES_X {
- for col in 0..RES_Y {
- back.cells[row][col] = front.new_state(row, col);
- }
- }
- back.randomize_border();
-
- self.swap_grids();
- }
-
- fn grids(&mut self) -> (&Grid, &mut Grid) {
- match self.front_grid {
- FrontGrid::A => (&self.grid_a, &mut self.grid_b),
- FrontGrid::B => (&self.grid_b, &mut self.grid_a),
- }
- }
-
- fn front_grid(&self) -> &Grid {
- match self.front_grid {
- FrontGrid::A => &self.grid_a,
- FrontGrid::B => &self.grid_b,
- }
- }
-
- fn swap_grids(&mut self) {
- self.front_grid = match self.front_grid {
- FrontGrid::A => FrontGrid::B,
- FrontGrid::B => FrontGrid::A,
- }
- }
-}
-
-impl Distribution<Cell> for Standard {
- fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Cell {
- if rng.gen() {
- Cell::Alive
- } else {
- Cell::Dead { since: 0xff }
- }
- }
-}