grass
This commit is contained in:
parent
4114003688
commit
26c2b2970f
@ -227,7 +227,7 @@ impl<'a> Graphics<'a> {
|
|||||||
// request it.
|
// request it.
|
||||||
self.window.request_redraw();
|
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();
|
frame.present();
|
||||||
}
|
}
|
||||||
fn update(&mut self) {
|
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.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.index_buf, 0, bytemuck::cast_slice(&self.state.indices));
|
||||||
self.queue.write_buffer(&self.uniforms_buf, 0, bytemuck::cast_slice(&[self.state.uniforms]));
|
self.queue.write_buffer(&self.uniforms_buf, 0, bytemuck::cast_slice(&[self.state.uniforms]));
|
||||||
|
139
src/state.rs
139
src/state.rs
@ -2,11 +2,12 @@ use std::time::Instant;
|
|||||||
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
|
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use voronoice::{BoundingBox, Point, Voronoi, VoronoiBuilder, VoronoiCell};
|
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};
|
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)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@ -15,46 +16,37 @@ enum CellKind {
|
|||||||
Sea,
|
Sea,
|
||||||
Plain,
|
Plain,
|
||||||
Beach,
|
Beach,
|
||||||
Forest
|
Forest,
|
||||||
}
|
Dirt,
|
||||||
impl CellKind {
|
Stone
|
||||||
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<u8> 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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CellData {
|
struct CellData {
|
||||||
kind: CellKind,
|
kind: CellKind,
|
||||||
cell: usize,
|
cell: usize,
|
||||||
z: f32
|
z: f32,
|
||||||
|
moisture: f32
|
||||||
}
|
}
|
||||||
impl CellData {
|
impl CellData {
|
||||||
fn new(kind: CellKind, cell: usize, z: f32) -> Self {
|
fn new(kind: CellKind, cell: usize, z: f32, moisture: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind,
|
kind,
|
||||||
cell,
|
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]
|
+ ((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
|
- ((site.x.powi(2)+site.y.powi(2)).sqrt()*0.5) // Distance - [0; sqrt(2)] * 0.5
|
||||||
).clamp(0., 1.);
|
).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 {
|
let k = if z <= 0.5 {
|
||||||
CellKind::Sea
|
CellKind::Sea
|
||||||
} else if z <= 0.52 {
|
} else if z <= 0.52 {
|
||||||
CellKind::Beach
|
CellKind::Beach
|
||||||
|
} else if z < 0.8 {
|
||||||
|
CellKind::Dirt
|
||||||
} else {
|
} else {
|
||||||
let m = (
|
CellKind::Stone
|
||||||
(moisture_noise.get([site.x, site.y])+1.)/2. // Noise + [0; 1]
|
|
||||||
).clamp(0., 1.);
|
|
||||||
if m > 0.5 {
|
|
||||||
CellKind::Forest
|
|
||||||
} else {
|
|
||||||
CellKind::Plain
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
cells_data.push(CellData::new(k, i, z as f32));
|
cells_data.push(CellData::new(k, i, z as f32, m));
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
voronoi,
|
voronoi,
|
||||||
@ -120,8 +110,11 @@ pub struct State {
|
|||||||
pub vertices: Vec<Vertex>,
|
pub vertices: Vec<Vertex>,
|
||||||
pub indices: Vec<u32>,
|
pub indices: Vec<u32>,
|
||||||
pub uniforms: Uniforms,
|
pub uniforms: Uniforms,
|
||||||
|
map: Map,
|
||||||
start: Instant,
|
start: Instant,
|
||||||
map: Map
|
frame: usize,
|
||||||
|
selected_tile: usize,
|
||||||
|
mouse_pressed: bool
|
||||||
}
|
}
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -130,20 +123,52 @@ impl State {
|
|||||||
indices: vec![],
|
indices: vec![],
|
||||||
uniforms: Uniforms::default(),
|
uniforms: Uniforms::default(),
|
||||||
start: Instant::now(),
|
start: Instant::now(),
|
||||||
map: Map::new(0)
|
frame: 0,
|
||||||
|
map: Map::new(0),
|
||||||
|
selected_tile: 0,
|
||||||
|
mouse_pressed: false
|
||||||
};
|
};
|
||||||
s.update();
|
s.render();
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
pub fn input(&mut self, event: Event<()>) {
|
pub fn input(&mut self, event: Event<()>, window: &Window) {
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => {
|
Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => {
|
||||||
if let state = ElementState::Pressed {
|
if state.is_pressed() {
|
||||||
match button {
|
match button {
|
||||||
MouseButton::Left => self.map = Map::new(self.map.seed + 1),
|
MouseButton::Left => {
|
||||||
MouseButton::Right => self.map = Map::new(self.map.seed - 1),
|
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 }, ..} => {
|
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.vertices = Vec::new();
|
||||||
self.indices = Vec::new();
|
self.indices = Vec::new();
|
||||||
|
|
||||||
for (c, data) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()) {
|
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::<Vec<_>>();
|
let vs = c.iter_vertices().collect::<Vec<_>>();
|
||||||
let i = self.vertices.len() as u32;
|
let i = self.vertices.len() as u32;
|
||||||
for v in vs.iter() {
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user