176 lines
5.9 KiB
Rust
176 lines
5.9 KiB
Rust
|
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);
|
||
|
}
|
||
|
}
|