diff --git a/src/graphics.rs b/src/graphics.rs index 487fa7e..8ff004f 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -227,7 +227,7 @@ impl<'a> Graphics<'a> { // request it. self.window.request_redraw(); }, - e => self.state.input(e) + e => self.state.input(e, &self.window) } }) @@ -272,7 +272,8 @@ impl<'a> Graphics<'a> { frame.present(); } fn update(&mut self) { - self.state.update(); + self.state.update_if_needed(); + self.state.render(); self.queue.write_buffer(&self.vertex_buf, 0, bytemuck::cast_slice(&self.state.vertices)); self.queue.write_buffer(&self.index_buf, 0, bytemuck::cast_slice(&self.state.indices)); self.queue.write_buffer(&self.uniforms_buf, 0, bytemuck::cast_slice(&[self.state.uniforms])); diff --git a/src/state.rs b/src/state.rs index 775fcd1..4070cb1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,11 +2,12 @@ use std::time::Instant; use noise::{Fbm, MultiFractal, NoiseFn, Perlin}; use rand::prelude::*; use voronoice::{BoundingBox, Point, Voronoi, VoronoiBuilder, VoronoiCell}; -use winit::event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent}; +use winit::{event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent}, window::Window}; use crate::graphics::{Uniforms, Vertex}; -pub const SQRT_3: f32 = 1.732050807568877293527446341505872367; +const SQRT_3: f32 = 1.732050807568877293527446341505872367; +const FRAMERATE: usize = 10; // Update per second #[repr(u8)] #[derive(Debug, Clone, Copy)] @@ -15,46 +16,37 @@ enum CellKind { Sea, Plain, Beach, - Forest -} -impl CellKind { - const VARIANTS: u8 = 3; - fn color(&self) -> [f32; 4] { - // let mut rng = thread_rng(); - // [rng.gen(), rng.gen(), rng.gen(), 1.] - match self { - Self::Void => [0.; 4], - Self::Sea => [0., 0., 1., 1.], - Self::Plain => [0., 1., 0., 1.], - Self::Beach => [1., 1., 0., 1.], - Self::Forest => [0., 0.5, 0., 1.] - } - } -} -impl From for CellKind { - fn from(value: u8) -> Self { - match value { - 0 => Self::Void, - 1 => Self::Sea, - 2 => Self::Plain, - 3 => Self::Beach, - 4 => Self::Forest, - _ => panic!("Invalid cell kind") - } - } + Forest, + Dirt, + Stone } struct CellData { kind: CellKind, cell: usize, - z: f32 + z: f32, + moisture: f32 } impl CellData { - fn new(kind: CellKind, cell: usize, z: f32) -> Self { + fn new(kind: CellKind, cell: usize, z: f32, moisture: f32) -> Self { Self { kind, cell, - z + z, + moisture + } + } + fn color(&self) -> [f32; 4] { + // let mut rng = thread_rng(); + // [rng.gen(), rng.gen(), rng.gen(), 1.] + match self.kind { + CellKind::Void => [0.; 4], + CellKind::Sea => [0., 0., 1., 1.], + CellKind::Plain => [0., 1., 0., 1.], + CellKind::Beach => [0.82, 0.84, 0.51, 1.], + CellKind::Forest => [0., 0.5, 0., 1.], + CellKind::Dirt => [0.53 - (self.moisture*0.4), 0.38-(self.moisture*0.4), 0.29-(self.moisture*0.4), 1.], + CellKind::Stone => [0.5, 0.5, 0.5, 1.] } } } @@ -92,21 +84,19 @@ impl Map { + ((z_noise.get([site.x, site.y])+1.)/2.) // Noise + [0; 1] - ((site.x.powi(2)+site.y.powi(2)).sqrt()*0.5) // Distance - [0; sqrt(2)] * 0.5 ).clamp(0., 1.); + let m = ( + (moisture_noise.get([site.x, site.y])+1.)/2. // Noise + [0; 1] + ).clamp(0., 1.) as f32; let k = if z <= 0.5 { CellKind::Sea } else if z <= 0.52 { CellKind::Beach + } else if z < 0.8 { + CellKind::Dirt } else { - let m = ( - (moisture_noise.get([site.x, site.y])+1.)/2. // Noise + [0; 1] - ).clamp(0., 1.); - if m > 0.5 { - CellKind::Forest - } else { - CellKind::Plain - } + CellKind::Stone }; - cells_data.push(CellData::new(k, i, z as f32)); + cells_data.push(CellData::new(k, i, z as f32, m)); } Self { voronoi, @@ -120,8 +110,11 @@ pub struct State { pub vertices: Vec, pub indices: Vec, pub uniforms: Uniforms, + map: Map, start: Instant, - map: Map + frame: usize, + selected_tile: usize, + mouse_pressed: bool } impl State { pub fn new() -> Self { @@ -130,20 +123,52 @@ impl State { indices: vec![], uniforms: Uniforms::default(), start: Instant::now(), - map: Map::new(0) + frame: 0, + map: Map::new(0), + selected_tile: 0, + mouse_pressed: false }; - s.update(); + s.render(); s } - pub fn input(&mut self, event: Event<()>) { + pub fn input(&mut self, event: Event<()>, window: &Window) { match event { Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => { - if let state = ElementState::Pressed { + if state.is_pressed() { match button { - MouseButton::Left => self.map = Map::new(self.map.seed + 1), - MouseButton::Right => self.map = Map::new(self.map.seed - 1), + MouseButton::Left => { + self.mouse_pressed = true; + }, + MouseButton::Right => self.map = Map::new(self.map.seed + 1), _ => {} }; + } else { + match button { + MouseButton::Left => { + self.mouse_pressed = false; + }, + _ => {} + } + } + }, + Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, ..} => { + dbg!(&position); + let w_size = window.inner_size(); + let pos = Point { + x: ((2.*position.x/(w_size.width as f64))-1.)*(self.uniforms.camera[2] as f64), + y: (1.-(2.*position.y/(w_size.height as f64)))*(self.uniforms.camera[2] as f64) + }; + let c = self.map.voronoi.cell(self.selected_tile); + if self.mouse_pressed { + for i in c.iter_path(pos) { + self.selected_tile = i; + let c = &mut self.map.cells_data[self.selected_tile]; + if let CellKind::Dirt = c.kind { + c.kind = CellKind::Forest; + } + } + } else { + self.selected_tile = c.iter_path(pos).last().unwrap(); } }, Event::DeviceEvent { event: DeviceEvent::MouseWheel { delta }, ..} => { @@ -155,12 +180,17 @@ impl State { _ => {} } } - pub fn update(&mut self) { + pub fn render(&mut self) { self.vertices = Vec::new(); self.indices = Vec::new(); for (c, data) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()) { - let color = data.kind.color(); + let mut color = data.color(); + if c.site() == self.selected_tile { + color[0] = (color[0]+0.4).clamp(0., 1.); + color[1] = (color[1]+0.4).clamp(0., 1.); + color[2] = (color[2]+0.4).clamp(0., 1.); + } let vs = c.iter_vertices().collect::>(); let i = self.vertices.len() as u32; for v in vs.iter() { @@ -173,4 +203,13 @@ impl State { } } } + pub fn update_if_needed(&mut self) { + while self.start.elapsed().as_secs_f32() > (self.frame as f32) / (FRAMERATE as f32) { + self.update(); + } + } + pub fn update(&mut self) { + self.frame += 1; + + } } \ No newline at end of file