forestiles/src/state.rs

176 lines
5.9 KiB
Rust
Raw Normal View History

2024-08-22 17:21:34 +01:00
use std::time::Instant;
use rand::prelude::*;
use winit::event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent};
use crate::graphics::{Uniforms, Vertex};
pub const SQRT_3: f32 = 1.732050807568877293527446341505872367;
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
enum CellKind {
Void,
Sea,
Grass,
}
impl CellKind {
const VALID_CHARS: [char; 3] = ['v', 's', 'g'];
fn color(&self) -> [f32; 4] {
match self {
Self::Void => [0.; 4],
Self::Sea => [0., 0., 1., 1.],
Self::Grass => [0., 1., 0., 1.]
}
}
}
impl From<char> for CellKind {
fn from(value: char) -> Self {
match value {
'v' => Self::Void,
's' => Self::Sea,
'g' => Self::Grass,
_ => panic!("Invalid cell kind")
}
}
}
impl From<u8> for CellKind {
fn from(value: u8) -> Self {
match value {
0 => Self::Void,
1 => Self::Sea,
2 => Self::Grass,
_ => panic!("Invalid cell kind")
}
}
}
struct Cell {
kind: CellKind
}
impl Cell {
const RADIUS: f32 = 1.;
fn new(kind: CellKind) -> Self {
Self {
kind
}
}
}
struct Map {
cells: [Cell; Self::SIZE]
}
impl Map {
const HEIGHT: usize = 10;
const WIDTH: usize = 10;
const SIZE: usize = Self::HEIGHT*Self::WIDTH;
fn new() -> Self {
std::array::from_fn(|_| thread_rng().gen_range(1..=2)).into()
// "sgssv
// ggsvg
// gsvvs
// vgsgs
// ssggs".into()
}
fn enumerate<'a>(&'a self) -> std::iter::Map<std::iter::Enumerate<std::slice::Iter<'a, Cell>>, fn((usize, &Cell)) -> ([usize; 2], &Cell)> {
self.cells.iter().enumerate().map(|(i, c)| ([i % Self::HEIGHT, i / Self::WIDTH], c))
}
}
impl From<&str> for Map {
fn from(value: &str) -> Self {
let mut chars = value.chars().filter(|c| CellKind::VALID_CHARS.contains(c));
let cells = std::array::from_fn(|_| Cell::new(chars.next().expect("Invalid map size").into()));
Self { cells }
}
}
impl From<[u8; Map::SIZE]> for Map {
fn from(value: [u8; Map::SIZE]) -> Self {
Self { cells: value.map(|c| Cell::new(c.into())) }
}
}
pub struct State {
pub vertices: Vec<Vertex>,
pub indices: Vec<u32>,
pub uniforms: Uniforms,
start: Instant,
map: Map
}
impl State {
pub fn new() -> Self {
let mut s = Self {
vertices: vec![],
indices: vec![],
uniforms: Uniforms::default(),
start: Instant::now(),
map: Map::new()
};
s.update();
s
}
pub fn input(&mut self, event: Event<()>) {
match event {
Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => {
if let state = ElementState::Pressed {
self.uniforms.camera[2] += match button {
MouseButton::Left => 0.1,
MouseButton::Right => -0.1,
_ => 0.
};
}
},
// Event::WindowEvent { event: WindowEvent::MouseWheel { delta, ..}, ..} => {
// self.uniforms.camera[2] -= match delta {
// MouseScrollDelta::PixelDelta(pos) => pos.y as f32,
// MouseScrollDelta::LineDelta(_, y) => y
// };
// },
Event::DeviceEvent { event: DeviceEvent::MouseWheel { delta }, ..} => {
self.uniforms.camera[2] += match delta {
MouseScrollDelta::PixelDelta(pos) => pos.y as f32,
MouseScrollDelta::LineDelta(_, y) => y
};
},
_ => {}
}
}
pub fn update(&mut self) {
self.vertices = Vec::with_capacity(self.map.cells.len()*6);
self.indices = Vec::with_capacity(self.map.cells.len()*12);
for ([x, y], c) in self.map.enumerate() {
let x = x as f32;
let y = y as f32;
let i = self.vertices.len();
let color = c.kind.color();
let center = [(0.5+x+((y%2.)*0.5)) * (SQRT_3*Cell::RADIUS), -(0.5+y)*(1.5*Cell::RADIUS)];
// self.vertices.push(Vertex { pos: [center[0], center[1], 0.], color });
// self.vertices.push(Vertex { pos: [center[0]+0.1, center[1]+0.1, 0.], color });
// self.vertices.push(Vertex { pos: [center[0]-0.1, center[1]+0.1, 0.], color });
self.vertices.push(Vertex { pos: [center[0], center[1]+Cell::RADIUS, 0.], color: color.clone() });
self.vertices.push(Vertex { pos: [center[0]-(0.5*SQRT_3*Cell::RADIUS), center[1]+(0.5*Cell::RADIUS), 0.], color: color.clone() });
self.vertices.push(Vertex { pos: [center[0]+(0.5*SQRT_3*Cell::RADIUS), center[1]+(0.5*Cell::RADIUS), 0.], color: color.clone() });
self.vertices.push(Vertex { pos: [center[0]-(0.5*SQRT_3*Cell::RADIUS), center[1]-(0.5*Cell::RADIUS), 0.], color: color.clone() });
self.vertices.push(Vertex { pos: [center[0]+(0.5*SQRT_3*Cell::RADIUS), center[1]-(0.5*Cell::RADIUS), 0.], color: color.clone() });
self.vertices.push(Vertex { pos: [center[0], center[1]-Cell::RADIUS, 0.], color: color.clone() });
self.indices.push(i as u32);
self.indices.push((i+1) as u32);
self.indices.push((i+2) as u32);
self.indices.push((i+1) as u32);
self.indices.push((i+3) as u32);
self.indices.push((i+2) as u32);
self.indices.push((i+3) as u32);
self.indices.push((i+4) as u32);
self.indices.push((i+2) as u32);
self.indices.push((i+3) as u32);
self.indices.push((i+5) as u32);
self.indices.push((i+4) as u32);
}
// dbg!(&self.vertices, &self.indices, &self.uniforms);
// dbg!(self.vertices.len(), self.indices.len(), &self.uniforms);
}
}