summaryrefslogtreecommitdiff
path: root/src/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.rs')
-rw-r--r--src/state.rs514
1 files changed, 0 insertions, 514 deletions
diff --git a/src/state.rs b/src/state.rs
deleted file mode 100644
index 09f0f77..0000000
--- a/src/state.rs
+++ /dev/null
@@ -1,514 +0,0 @@
-#![allow(dead_code, unused_variables)]
-use std::collections::HashMap;
-use bimap::BiHashMap;
-use enum_map::{enum_map, Enum, EnumMap};
-use serde::{Serialize, Deserialize};
-
-use crate::{audio, context, framebuffer, shader, utils};
-
-const DELTA_TIME: f64 = 1.0 / 60.0;
-
-pub struct WinitWaker {}
-impl WinitWaker {
- fn new() -> Self { Self {} }
-}
-impl std::task::Wake for WinitWaker {
- fn wake(self: std::sync::Arc<Self>) {}
-}
-
-pub struct Response {
- pub url: String,
- pub status: reqwest::StatusCode,
- pub body: bytes::Bytes,
-}
-
-pub trait Game {
- fn initialize(&self, ctx: &context::Context, st: &State) -> utils::Erm<()> { Ok(()) }
- fn finalize(&self, ctx: &context::Context, st: &State) -> utils::Erm<()> { Ok(()) }
- fn initialize_audio(&self, ctx: &context::Context, st: &State, actx: &audio::Context) ->
- HashMap<String, audio::Audio>
- {
- HashMap::new()
- }
- fn finish_title(&mut self, st: &mut State) {}
- fn mouse_move(&mut self, ctx: &context::Context, st: &mut State, x: i32, y: i32) {}
- fn mouse_press(&mut self, ctx: &context::Context, st: &mut State) {}
- fn request_return(&mut self, ctx: &context::Context, st: &mut State, res: Response) {}
- fn update(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) }
- fn render(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) }
-}
-
-#[derive(Debug, Enum, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub enum Key {
- Up, Down, Left, Right,
- A, B, L, R,
- Start, Select,
-}
-pub const KEYS: [Key; 10] = [
- Key::Up, Key::Down, Key::Left, Key::Right,
- Key::A, Key::B, Key::L, Key::R,
- Key::Start, Key::Select,
-];
-pub struct Keys {
- pub pressed: EnumMap<Key, bool>,
- pub new: EnumMap<Key, bool>,
-}
-impl Keys {
- pub fn new() -> Self {
- Self {
- pressed: enum_map! {
- Key::Up => false, Key::Down => false, Key::Left => false, Key::Right => false,
- Key::A => false, Key::B => false, Key::L => false, Key::R => false,
- Key::Start => false, Key::Select => false,
- },
- new: enum_map! {
- Key::Up => false, Key::Down => false, Key::Left => false, Key::Right => false,
- Key::A => false, Key::B => false, Key::L => false, Key::R => false,
- Key::Start => false, Key::Select => false,
- },
- }
- }
- pub fn up(&self) -> bool { self.pressed[Key::Up] }
- pub fn down(&self) -> bool { self.pressed[Key::Down] }
- pub fn left(&self) -> bool { self.pressed[Key::Left] }
- pub fn right(&self) -> bool { self.pressed[Key::Right] }
- pub fn a(&self) -> bool { self.pressed[Key::A] }
- pub fn b(&self) -> bool { self.pressed[Key::B] }
- pub fn l(&self) -> bool { self.pressed[Key::L] }
- pub fn r(&self) -> bool { self.pressed[Key::R] }
- pub fn start(&self) -> bool { self.pressed[Key::Start] }
- pub fn select(&self) -> bool { self.pressed[Key::Select] }
- pub fn new_up(&mut self) -> bool { let ret = self.new[Key::Up]; self.new[Key::Up] = false; ret }
- pub fn new_down(&mut self) -> bool { let ret = self.new[Key::Down]; self.new[Key::Down] = false; ret }
- pub fn new_left(&mut self) -> bool { let ret = self.new[Key::Left]; self.new[Key::Left] = false; ret }
- pub fn new_right(&mut self) -> bool { let ret = self.new[Key::Right]; self.new[Key::Right] = false; ret }
- pub fn new_a(&mut self) -> bool { let ret = self.new[Key::A]; self.new[Key::A] = false; ret }
- pub fn new_b(&mut self) -> bool { let ret = self.new[Key::B]; self.new[Key::B] = false; ret }
- pub fn new_l(&mut self) -> bool { let ret = self.new[Key::L]; self.new[Key::L] = false; ret }
- pub fn new_r(&mut self) -> bool { let ret = self.new[Key::R]; self.new[Key::R] = false; ret }
- pub fn new_start(&mut self) -> bool { let ret = self.new[Key::Start]; self.new[Key::Start] = false; ret }
- pub fn new_select(&mut self) -> bool { let ret = self.new[Key::Select]; self.new[Key::Select] = false; ret }
-}
-
-pub struct PointLight {
- pub pos: glam::Vec3,
- pub color: glam::Vec3,
- pub attenuation: glam::Vec2,
-}
-
-type Timestamp = f64;
-
-#[cfg(target_arch = "wasm32")]
-pub type Keycode = winit::keyboard::KeyCode;
-
-#[cfg(not(target_arch = "wasm32"))]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Keycode {
- pub kc: glfw::Key
-}
-#[cfg(not(target_arch = "wasm32"))]
-impl Keycode {
- pub fn new(kc: glfw::Key) -> Self { Self { kc } }
-}
-#[cfg(not(target_arch = "wasm32"))]
-impl Serialize for Keycode {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where S: serde::Serializer {
- (self.kc as i32).serialize(serializer)
- }
-}
-#[cfg(not(target_arch = "wasm32"))]
-impl<'de> Deserialize<'de> for Keycode {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where D: serde::Deserializer<'de> {
- i32::deserialize(deserializer)
- .map(|x| unsafe {
- std::mem::transmute(x)
- })
- }
-}
-
-pub struct State {
- pub acc: f64,
- pub last: Timestamp,
- pub tick: u64,
-
- pub rebinding: Option<Key>,
- pub keybindings: BiHashMap<Keycode, Key>,
- pub keys: Keys,
-
- pub screen: framebuffer::Framebuffer,
- pub render_framebuffer: framebuffer::Framebuffer,
- pub shader_upscale: shader::Shader,
- pub audio: Option<audio::Assets>,
-
- pub projection: glam::Mat4,
- pub camera: (glam::Vec3, glam::Vec3, glam::Vec3),
- pub lighting: (glam::Vec3, glam::Vec3, glam::Vec3),
- pub point_lights: Vec<PointLight>,
-
- pub waker_ctx: std::task::Context<'static>,
- pub http_client: reqwest::Client,
- pub request: Option<std::pin::Pin<Box<dyn std::future::Future<Output = reqwest::Result<Response>>>>>,
-
- pub log: Vec<(u64, String)>,
-}
-
-#[cfg(target_arch = "wasm32")]
-pub fn now(ctx: &context::Context) -> Timestamp {
- ctx.performance.now() / 1000.0
-}
-
-#[cfg(not(target_arch = "wasm32"))]
-pub fn now(ctx: &context::Context) -> Timestamp {
- let elapsed = ctx.start_instant.elapsed();
- let ms = elapsed.as_millis();
- (ms as f64) / 1000.0
-}
-
-#[cfg(target_arch = "wasm32")]
-pub fn default_keybindings() -> BiHashMap<Keycode, Key> {
- BiHashMap::from_iter(vec![
- (winit::keyboard::KeyCode::KeyW, Key::Up),
- (winit::keyboard::KeyCode::KeyS, Key::Down),
- (winit::keyboard::KeyCode::KeyA, Key::Left),
- (winit::keyboard::KeyCode::KeyD, Key::Right),
- (winit::keyboard::KeyCode::Digit1, Key::A),
- (winit::keyboard::KeyCode::Digit2, Key::B),
- (winit::keyboard::KeyCode::KeyQ, Key::L),
- (winit::keyboard::KeyCode::KeyE, Key::R),
- (winit::keyboard::KeyCode::Tab, Key::Start),
- (winit::keyboard::KeyCode::Space, Key::Select),
- ])
-}
-
-#[cfg(not(target_arch = "wasm32"))]
-pub fn default_keybindings() -> BiHashMap<Keycode, Key> {
- BiHashMap::from_iter(vec![
- (Keycode::new(glfw::Key::W), Key::Up),
- (Keycode::new(glfw::Key::S), Key::Down),
- (Keycode::new(glfw::Key::A), Key::Left),
- (Keycode::new(glfw::Key::D), Key::Right),
- (Keycode::new(glfw::Key::Num1), Key::A),
- (Keycode::new(glfw::Key::Num2), Key::B),
- (Keycode::new(glfw::Key::Q), Key::L),
- (Keycode::new(glfw::Key::E), Key::R),
- (Keycode::new(glfw::Key::Tab), Key::Start),
- (Keycode::new(glfw::Key::Space), Key::Select),
- ])
-}
-
-impl State {
- pub fn new(ctx: &context::Context) -> Self {
- let screen = framebuffer::Framebuffer::screen(ctx);
- let render_framebuffer = framebuffer::Framebuffer::new(
- ctx,
- &glam::Vec2::new(ctx.render_width, ctx.render_height),
- &glam::Vec2::new(0.0, 0.0),
- );
- let shader_upscale = shader::Shader::new_nolib(
- ctx,
- include_str!("assets/shaders/scale/vert.glsl"),
- include_str!("assets/shaders/scale/frag.glsl"),
- );
-
- let waker = std::sync::Arc::new(WinitWaker::new());
- let cwaker = Box::leak(Box::new(waker.into()));
- let waker_ctx = std::task::Context::from_waker(cwaker);
-
- let acc = 0.0;
- let last = now(ctx);
-
- Self {
- acc,
- last,
- // we initialize the tick to 1000, which allows us to use "0" as the default time for
- // various animation starts on entities without having them all play at game start
- tick: 1000,
-
- rebinding: None,
- keybindings: default_keybindings(),
- keys: Keys::new(),
-
- screen,
- render_framebuffer,
- shader_upscale,
- audio: None,
-
- projection: glam::Mat4::perspective_lh(
- std::f32::consts::PI / 4.0,
- ctx.render_width / ctx.render_height,
- // 0.1,
- 0.5,
- 50.0,
- ),
- camera: (glam::Vec3::new(0.0, 0.0, 0.0), glam::Vec3::new(0.0, 0.0, 1.0), glam::Vec3::new(0.0, 1.0, 0.0)),
- lighting: (
- glam::Vec3::new(1.0, 1.0, 1.0),
- glam::Vec3::new(1.0, 1.0, 1.0),
- glam::Vec3::new(1.0, -1.0, 1.0),
- ),
- point_lights: Vec::new(),
-
- waker_ctx,
- http_client: reqwest::Client::new(),
- request: None,
-
- log: Vec::new(),
- }
- }
-
- pub fn write_log(&mut self, e: &str) {
- log::info!("log: {}", e.to_owned());
- self.log.push((self.tick, e.to_owned()));
- }
-
- pub fn handle_resize(&mut self, ctx: &context::Context) {
- self.screen = framebuffer::Framebuffer::screen(ctx);
- }
-
- pub fn move_camera(
- &mut self,
- _ctx: &context::Context,
- pos: &glam::Vec3,
- dir: &glam::Vec3,
- up: &glam::Vec3,
- ) {
- self.camera = (pos.clone(), dir.clone(), up.clone());
- }
-
- pub fn set_lighting(
- &mut self,
- _ctx: &context::Context,
- ambient: &glam::Vec3,
- color: &glam::Vec3,
- dir: &glam::Vec3,
- ) {
- self.lighting = (ambient.clone(), color.clone(), dir.clone());
- }
-
- pub fn add_point_light(
- &mut self,
- _ctx: &context::Context,
- pos: &glam::Vec3,
- color: &glam::Vec3,
- attenuation: &glam::Vec2,
- ) {
- self.point_lights.push(
- PointLight {
- pos: pos.clone(),
- color: color.clone(),
- attenuation: attenuation.clone(),
- },
- );
- }
-
- pub fn clear_point_lights(&mut self, _ctx: &context::Context) {
- self.point_lights.clear();
- }
-
- pub fn view(&self) -> glam::Mat4 {
- glam::Mat4::look_to_lh(
- self.camera.0,
- self.camera.1,
- self.camera.2,
- )
- }
-
- pub fn bind_3d_helper(&mut self, ctx: &context::Context, shader: &shader::Shader, plc: usize) {
- shader.bind(ctx);
- shader.set_mat4(ctx, "projection", &self.projection);
- shader.set_mat4(ctx, "view", &self.view());
- shader.set_vec3(
- ctx, "light_ambient_color",
- &self.lighting.0,
- );
- shader.set_vec3(
- ctx, "light_dir_color",
- &self.lighting.1,
- );
- shader.set_vec3(
- ctx, "light_dir",
- &self.lighting.2.normalize(),
- );
- shader.set_i32(
- ctx, &format!("light_count"),
- plc as _,
- );
- }
-
- pub fn bind_3d_no_point_lights(&mut self, ctx: &context::Context, shader: &shader::Shader) {
- self.bind_3d_helper(ctx, shader, 0);
- }
-
- pub fn bind_3d(&mut self, ctx: &context::Context, shader: &shader::Shader) {
- let plc = self.point_lights.len().min(5);
- self.bind_3d_helper(ctx, shader, plc);
- if plc > 0 {
- let lpos: Vec<_> = self.point_lights.iter().take(plc).map(|l| l.pos).collect();
- shader.set_vec3_array(
- ctx, &format!("light_pos[0]"),
- &lpos,
- );
- let lcolor: Vec<_> = self.point_lights.iter().take(plc).map(|l| l.color).collect();
- shader.set_vec3_array(
- ctx, &format!("light_color[0]"),
- &lcolor,
- );
- let lattenuation: Vec<_> = self.point_lights.iter().take(plc).map(|l| l.attenuation).collect();
- shader.set_vec2_array(
- ctx, &format!("light_attenuation[0]"),
- &lattenuation,
- );
- }
- }
-
- pub fn bind_2d(&mut self, ctx: &context::Context, shader: &shader::Shader) {
- shader.bind(ctx);
- shader.set_mat4(&ctx, "projection", &glam::Mat4::IDENTITY);
- shader.set_mat4(
- ctx, "view",
- &glam::Mat4::from_scale(
- glam::Vec3::new(
- 2.0 / ctx.render_width,
- 2.0 / ctx.render_height,
- 1.0,
- ),
- ),
- );
- }
-
- pub fn mouse_moved<G>(
- &mut self,
- ctx: &context::Context,
- x: f32, y: f32,
- game: &mut G
- ) where G: Game
- {
- let rx = ((x - self.screen.offsets.x) * ctx.render_width / self.screen.dims.x) as i32;
- let ry = ((y - self.screen.offsets.y) * ctx.render_height / self.screen.dims.y) as i32;
- if !(rx < 0 || rx >= ctx.render_width as i32 || ry < 0 || ry >= ctx.render_height as i32) {
- game.mouse_move(ctx, self, rx, ry);
- }
- }
-
- pub fn mouse_pressed<G>(
- &mut self,
- ctx: &context::Context,
- game: &mut G
- ) where G: Game {
- log::info!("click");
- if self.audio.is_none() {
- self.audio = Some(audio::Assets::new(|actx| {
- game.initialize_audio(ctx, &self, actx)
- }));
- game.finish_title(self);
- }
- game.mouse_press(ctx, self);
- }
-
- pub fn mouse_released(
- &mut self,
- _ctx: &context::Context,
- ) {
- }
-
- pub fn key_pressed(
- &mut self,
- _ctx: &context::Context,
- key: Keycode,
- ) {
- #[cfg(target_arch = "wasm32")]
- let rebind = key == winit::keyboard::KeyCode::F12;
- #[cfg(not(target_arch = "wasm32"))]
- let rebind = key.kc == glfw::Key::F12;
- if rebind {
- self.keybindings = default_keybindings();
- self.rebinding = None;
- self.write_log("Reset keybindings!");
- } else if let Some(k) = self.rebinding {
- self.keybindings.insert(key, k);
- self.rebinding = None;
- } else if let Some(k) = self.keybindings.get_by_left(&key) {
- self.keys.pressed[*k] = true;
- self.keys.new[*k] = true;
- }
- }
-
- pub fn key_released(
- &mut self,
- _ctx: &context::Context,
- key: Keycode,
- ) {
- if let Some(k) = self.keybindings.get_by_left(&key) {
- self.keys.pressed[*k] = false;
- }
- }
-
- /// Return the first keybinding for the given virtual key
- pub fn keybinding_for(&self, k: &Key) -> Option<String> {
- if let Some(kc) = self.keybindings.get_by_right(k) {
- Some(format!("{:?}", kc))
- } else {
- None
- }
- }
-
- pub fn rebind_key(&mut self, k: &Key) {
- self.rebinding = Some(*k);
- }
-
- pub fn request<F>(&mut self, f: F)
- where F: Fn(&reqwest::Client) -> reqwest::RequestBuilder
- {
- let builder = f(&self.http_client);
- let fut = async {
- let resp = builder.send().await?;
- let url = resp.url().clone().to_string();
- let status = resp.status().clone();
- let body = resp.bytes().await?;
- reqwest::Result::Ok(Response {
- url,
- status,
- body,
- })
- };
- self.request = Some(Box::pin(fut));
- }
-
- pub fn requesting(&self) -> bool { self.request.is_some() }
-
- pub fn request_returned<G>(&mut self, ctx: &context::Context, game: &mut G, res: Response)
- where G: Game
- {
- game.request_return(ctx, self, res);
- }
-
- pub fn run_update<G>(&mut self, ctx: &context::Context, game: &mut G) -> utils::Erm<()> where G: Game {
- let now = now(ctx);
- let diff = now - self.last;
-
- // update, if enough time has accumulated since last update
- if diff >= DELTA_TIME {
- self.last = now;
- self.tick += 1;
- game.update(ctx, self)?;
- self.acc = 0.0;
- }
- Ok(())
- }
-
- pub fn run_render<G>(&mut self, ctx: &context::Context, game: &mut G) -> utils::Erm<()> where G: Game {
- self.render_framebuffer.bind(&ctx);
-
- game.render(ctx, self)?;
-
- self.screen.bind(&ctx);
- ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0));
- ctx.clear();
- self.shader_upscale.bind(&ctx);
- self.render_framebuffer.bind_texture(&ctx);
- ctx.render_no_geometry();
- Ok(())
- }
-}