diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/assets/audio/mrbeast.mp3 | bin | 0 -> 33837 bytes | |||
| -rw-r--r-- | src/assets/meshes/cube.obj | 34 | ||||
| -rw-r--r-- | src/assets/shaders/flat/frag.glsl | 11 | ||||
| -rw-r--r-- | src/assets/shaders/flat/vert.glsl | 4 | ||||
| -rw-r--r-- | src/assets/shaders/plane/frag.glsl | 23 | ||||
| -rw-r--r-- | src/assets/shaders/plane/vert.glsl | 11 | ||||
| -rw-r--r-- | src/assets/textures/test.png | bin | 714 -> 772 bytes | |||
| -rw-r--r-- | src/game.rs | 178 | ||||
| -rw-r--r-- | src/helpers.js | 13 | ||||
| -rw-r--r-- | src/index.css | 34 | ||||
| -rw-r--r-- | src/lib.rs | 5 | ||||
| -rw-r--r-- | src/main.rs | 6 | ||||
| -rw-r--r-- | src/room.rs | 346 |
13 files changed, 576 insertions, 89 deletions
diff --git a/src/assets/audio/mrbeast.mp3 b/src/assets/audio/mrbeast.mp3 Binary files differnew file mode 100644 index 0000000..8cf3d8a --- /dev/null +++ b/src/assets/audio/mrbeast.mp3 diff --git a/src/assets/meshes/cube.obj b/src/assets/meshes/cube.obj new file mode 100644 index 0000000..6c93e45 --- /dev/null +++ b/src/assets/meshes/cube.obj @@ -0,0 +1,34 @@ +# Blender 3.6.2 +# www.blender.org +o Cube +v 1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +s 0 +f 5/1/1 3/2/1 1/3/1 +f 3/1/2 8/2/2 4/3/2 +f 7/1/3 6/2/3 8/3/3 +f 2/1/4 8/2/4 6/3/4 +f 1/1/5 4/2/5 2/3/5 +f 5/1/6 2/2/6 6/3/6 +f 5/1/1 7/4/1 3/2/1 +f 3/1/2 7/4/2 8/2/2 +f 7/1/3 5/4/3 6/2/3 +f 2/1/4 4/4/4 8/2/4 +f 1/1/5 3/4/5 4/2/5 +f 5/1/6 1/4/6 2/2/6 diff --git a/src/assets/shaders/flat/frag.glsl b/src/assets/shaders/flat/frag.glsl deleted file mode 100644 index 7006a2b..0000000 --- a/src/assets/shaders/flat/frag.glsl +++ /dev/null @@ -1,11 +0,0 @@ -uniform sampler2D texture_data; - -void main() -{ - vec2 tcfull = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y); - vec4 texel = texture(texture_data, tcfull); - if (texel.a != 1.0) { - discard; - } - frag_color = texel; -} diff --git a/src/assets/shaders/flat/vert.glsl b/src/assets/shaders/flat/vert.glsl deleted file mode 100644 index e324f7e..0000000 --- a/src/assets/shaders/flat/vert.glsl +++ /dev/null @@ -1,4 +0,0 @@ -void main() -{ - default_main(); -}
\ No newline at end of file diff --git a/src/assets/shaders/plane/frag.glsl b/src/assets/shaders/plane/frag.glsl new file mode 100644 index 0000000..a323cc8 --- /dev/null +++ b/src/assets/shaders/plane/frag.glsl @@ -0,0 +1,23 @@ +uniform sampler2D texture_data; + +uniform vec2 texture_scale; +uniform vec2 texture_offset; +uniform float fog_distance; +uniform vec3 fog_color; +uniform float opacity; + +in float vertex_depth; + +void main() +{ + vec2 tcfull = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y); + vec4 texel = texture(texture_data, tcfull * texture_scale + texture_offset); + if (fog_distance > 0.0) { + float t = clamp(vertex_depth / fog_distance, 0.0, 1.0); + texel.rgb = mix(texel.rgb, fog_color, t); + if (t == 1.0) texel.a = 1.0; + } + texel.a *= opacity; + if (texel.a == 0.0) discard; + frag_color = texel; +} diff --git a/src/assets/shaders/plane/vert.glsl b/src/assets/shaders/plane/vert.glsl new file mode 100644 index 0000000..c8932a5 --- /dev/null +++ b/src/assets/shaders/plane/vert.glsl @@ -0,0 +1,11 @@ +out float vertex_depth; + +void main() +{ + vertex_texcoord = texcoord; + vec3 pos = (position * vec4(vertex, 1.0)).xyz; + vertex_fragpos = pos; + vec4 vpos = view * vec4(pos, 1.0); + vertex_depth = vpos.z; + gl_Position = projection * vpos; +} diff --git a/src/assets/textures/test.png b/src/assets/textures/test.png Binary files differindex 1f1edca..2b0227b 100644 --- a/src/assets/textures/test.png +++ b/src/assets/textures/test.png diff --git a/src/game.rs b/src/game.rs index 1abe66e..0596a2b 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,11 +1,16 @@ #![allow(dead_code, unused_variables)] -use std::collections::HashMap; +use std::{collections::HashMap, f32::consts::PI}; use teleia::*; +use crate::room; + +const MOUSE_SENSITIVITY: f32 = 0.01; +const PLAYER_SPEED: f32 = 0.1; +const PLAYER_RADIUS: f32 = 0.5; + struct Assets { font: font::Bitmap, - shader_flat: shader::Shader, - mesh_square: mesh::Mesh, + mesh_cube: mesh::Mesh, texture_test: texture::Texture, } @@ -13,53 +18,176 @@ impl Assets { fn new(ctx: &context::Context) -> Self { Self { font: font::Bitmap::default(ctx), - shader_flat: shader::Shader::new( - ctx, - include_str!("assets/shaders/flat/vert.glsl"), - include_str!("assets/shaders/flat/frag.glsl"), - ), - mesh_square: mesh::Mesh::from_obj(ctx, include_bytes!("assets/meshes/square.obj")), + mesh_cube: mesh::Mesh::from_obj(ctx, include_bytes!("assets/meshes/cube.obj")), texture_test: texture::Texture::new(ctx, include_bytes!("assets/textures/test.png")), } } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Mode { + Titlescreen, + Game, +} + pub struct Game { + mode: Mode, assets: Assets, + room_path: String, + room: room::Room, + mouse: (i32, i32), + camera_pitch: f32, + camera_yaw: f32, + player_pos: glam::Vec3, } impl Game { - pub fn new(ctx: &context::Context) -> Self { + pub fn new(ctx: &context::Context, room_path: &str) -> Self { Self { + mode: Mode::Titlescreen, assets: Assets::new(ctx), + room_path: room_path.to_owned(), + room: room::Room::new(ctx, shader::Shader::new(ctx, + include_str!("assets/shaders/plane/vert.glsl"), + include_str!("assets/shaders/plane/frag.glsl"), + )), + mouse: (ctx.render_width as i32 / 2, ctx.render_height as i32 / 2), + camera_pitch: 0.0, + camera_yaw: 0.0, + player_pos: glam::Vec3::new(0.0, 0.0, 0.0), } } + fn looking_at_art(&self, ctx: &context::Context, st: &mut state::State) -> bool { + let q = glam::Quat::from_rotation_y(self.camera_yaw); + let dir = q.mul_vec3(glam::Vec3::new(0.0, 0.0, 1.0)); + let p = self.player_pos + dir; + p.distance(glam::Vec3::ZERO) < 2.0 + } + fn player_height(&self) -> f32 { + 1.0 / self.room.config.size + } + fn player_speed(&self) -> f32 { + PLAYER_SPEED / self.room.config.size * self.room.config.speed + } } impl teleia::state::Game for Game { + fn initialize(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { + Ok(()) + } fn initialize_audio(&self, ctx: &context::Context, st: &state::State, actx: &audio::Context) -> HashMap<String, audio::Audio> { HashMap::from_iter(vec![ - ("test".to_owned(), audio::Audio::new(&actx, include_bytes!("assets/audio/test.wav"))), + ("mrbeast".to_owned(), audio::Audio::new(&actx, include_bytes!("assets/audio/mrbeast.mp3"))), ]) } - fn update(&mut self, _ctx: &context::Context, _st: &mut state::State) -> Erm<()> { + fn finish_title(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { + if self.mode == Mode::Titlescreen { + self.mode = Mode::Game; + ctx.lock_mouse(); + // TODO + if cfg!(target_arch = "wasm32") { + self.room.load_from_bytes(ctx, st, + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/room.ini")), + include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/FLOOR.png"), + include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/WALL.png"), + include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/ROOF.png"), + include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/ART.png"), + include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/CREDIT.png"), + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/MINI.png")), + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/INTERACT.png")), + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/LAYER.png")), + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/MUSIC.mp3")), + Some(include_bytes!("/home/llll/src/bapalon/DATA/NIGHT_1/ROOM_4/FOOT.wav")), + )?; + } else { + self.room.load(ctx, st, &self.room_path)?; + } + } + Ok(()) + } + fn mouse_press(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { + match self.mode { + Mode::Titlescreen => { + } + Mode::Game => { + self.room.credit_mode.toggle(st.tick); + }, + } + Ok(()) + } + fn mouse_move(&mut self, ctx: &context::Context, st: &mut state::State, x: i32, y: i32) -> Erm<()> { + match self.mode { + Mode::Titlescreen => { + } + Mode::Game => { + let dx = x - self.mouse.0; + let dy = y - self.mouse.1; + self.camera_yaw += dx as f32 * MOUSE_SENSITIVITY; + self.camera_pitch += dy as f32 * MOUSE_SENSITIVITY; + self.camera_pitch = self.camera_pitch.clamp(-PI/2.0 + 0.001, PI/2.0 - 0.001); + self.mouse = (x, y); + } + } + Ok(()) + } + fn update(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { + match self.mode { + Mode::Titlescreen => { + } + Mode::Game => { + let mut player_dir = glam::Vec3::ZERO; + if st.keys.up() { player_dir += glam::Vec3::new(0.0, 0.0, 1.0); } + if st.keys.down() { player_dir += glam::Vec3::new(0.0, 0.0, -1.0); } + if st.keys.left() { player_dir += glam::Vec3::new(-1.0, 0.0, 0.0); } + if st.keys.right() { player_dir += glam::Vec3::new(1.0, 0.0, 0.0); } + if player_dir != glam::Vec3::ZERO { + self.room.footstep(ctx, st)?; + player_dir = player_dir.normalize(); + self.player_pos += self.player_speed() + * glam::Quat::from_rotation_y(self.camera_yaw).mul_vec3(player_dir); + self.player_pos.x = self.player_pos.x.clamp( + -room::PLANE_SIZE + PLAYER_RADIUS, + room::PLANE_SIZE - PLAYER_RADIUS + ); + self.player_pos.z = self.player_pos.z.clamp( + -room::PLANE_SIZE + PLAYER_RADIUS, + room::PLANE_SIZE - PLAYER_RADIUS + ); + } + if self.looking_at_art(ctx, st) { + if !self.room.interact_mode.is_active() { + self.room.interact_mode.toggle(st.tick); + } + } else { + if self.room.interact_mode.is_active() { + self.room.interact_mode.toggle(st.tick); + } + } + let q = glam::Quat::from_euler(glam::EulerRot::YXZ, self.camera_yaw, self.camera_pitch, 0.0); + let dir = q.mul_vec3(glam::Vec3::new(0.0, 0.0, 1.0)); + st.move_camera(ctx, + &(self.player_pos + glam::Vec3::new(0.0, self.player_height(), 0.0)), + &dir, + &glam::Vec3::new(0.0, 1.0, 0.0), + ); + } + } Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { ctx.clear(); - self.assets.font.render_text( - ctx, st, - &glam::Vec2::new(0.0, 0.0), - "hello computer", - ); - st.bind_2d(ctx, &self.assets.shader_flat); - self.assets.texture_test.bind(ctx); - self.assets.shader_flat.set_position_2d( - ctx, st, - &glam::Vec2::new(40.0, 40.0), - &glam::Vec2::new(16.0, 16.0), - ); - self.assets.mesh_square.render(ctx); + match self.mode { + Mode::Titlescreen => { + self.assets.font.render_text( + ctx, st, + &glam::Vec2::new(0.0, 0.0), + "click to continue", + ); + } + Mode::Game => { + self.room.render(ctx, st, self.camera_yaw)?; + } + } Ok(()) } } diff --git a/src/helpers.js b/src/helpers.js deleted file mode 100644 index 20b86f4..0000000 --- a/src/helpers.js +++ /dev/null @@ -1,13 +0,0 @@ -let resized = false; - -export async function js_track_resized_setup() { - window.addEventListener("resize", () => { - resized = true; - }); -}; - -export function js_poll_resized() { - let ret = resized; - resized = false; - return ret; -} diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 323fa50..0000000 --- a/src/index.css +++ /dev/null @@ -1,34 +0,0 @@ -html { - touch-action: manipulation; -} -body { - background: #000000; -} -html, body { - overflow: hidden; - margin: 0 !important; - padding: 0 !important; - height: 100%; - width: 100%; -} -canvas { - margin-right: auto; - margin-left: auto; - display: block; - position: absolute; - top: 0%; - left: 50%; - transform: translate(-50%, 0%); - color: #000000; -} -.centered { - margin-right: auto; - margin-left: auto; - display: block; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - text-align: center; - image-transform: pixelated; -} @@ -1,4 +1,5 @@ mod game; +mod room; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -6,5 +7,7 @@ use wasm_bindgen::prelude::*; #[cfg(target_arch = "wasm32")] #[wasm_bindgen] pub fn main_js() { - teleia::run(240, 160, teleia::Options::empty(), game::Game::new); + teleia::run(240, 160, teleia::Options::empty(), + |ctx| game::Game::new(ctx, "broken path") + ); } diff --git a/src/main.rs b/src/main.rs index 25a240d..3c8ed4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ mod game; +mod room; #[cfg(not(target_arch = "wasm32"))] pub fn main() -> teleia::Erm<()> { - teleia::run("game", 240, 160, teleia::Options::empty(), game::Game::new) + let room_path = std::env::args().nth(1).unwrap(); + teleia::run("game", 640, 480, teleia::Options::FULLSCREEN_MOUSE, + |ctx| game::Game::new(ctx, &room_path) + ) } #[cfg(target_arch = "wasm32")] diff --git a/src/room.rs b/src/room.rs new file mode 100644 index 0000000..81ed88b --- /dev/null +++ b/src/room.rs @@ -0,0 +1,346 @@ +use std::{f32::consts::PI, path::{Path, PathBuf}}; + +use teleia::*; + +use rand::Rng; + +pub const PLANE_SIZE: f32 = 12.0; +pub const FOOTSTEP_TIME: u64 = 90; + +#[derive(Debug)] +pub struct Config { + pub name: String, + pub credits: String, + pub links: String, + pub size: f32, + pub speed: f32, + pub fov: f32, + pub texture_repeat: f32, + pub room_height: f32, + pub layer_frames: f32, + pub fog_color: glam::Vec3, + pub fog_end: f32, + pub mini_speed: f32, +} +impl Default for Config { + fn default() -> Self { + Self { + name: "".to_owned(), + credits: "".to_owned(), + links: "".to_owned(), + size: 1.0, + speed: 1.0, + fov: 55.0, + texture_repeat: 3.0, + room_height: 350.0, + layer_frames: 1.0, + fog_color: glam::Vec3::ZERO, + fog_end: -1.0, + mini_speed: 1.0, + } + } +} +impl Config { + pub fn from_room_ini(bs: Vec<u8>) -> Erm<Self> { + let mut ret = Self::default(); + let contents = String::from_utf8(bs)?; + let i = ini::Ini::load_from_str(&contents)?; + let Some(sec) = i.section::<&str>(None) else { return utils::erm_msg("failed to get properties"); }; + if let Some(x) = sec.get("name") { ret.name = x.to_owned(); } + if let Some(x) = sec.get("credits") { ret.credits = x.to_owned(); } + if let Some(x) = sec.get("links") { ret.links = x.to_owned(); } + if let Some(x) = sec.get("size") { ret.size = x.parse()?; } + if let Some(x) = sec.get("speed") { ret.speed = x.parse()?; } + if let Some(x) = sec.get("FOV") { ret.fov = x.parse()?; } + if let Some(x) = sec.get("Texture_Repeat") { ret.texture_repeat = x.parse()?; } + if let Some(x) = sec.get("Room_Height") { ret.room_height = x.parse::<f32>()? / 350.0; } + if let Some(x) = sec.get("Layer_Frames") { ret.layer_frames = x.parse()?; } + if let Some(x) = sec.get("Fog_Color") { + let num: u64 = x.parse()?; + ret.fog_color = glam::Vec3::new( + (num & 0xff) as f32 / 255.0, + (num >> 8 & 0xff) as f32 / 255.0, + (num >> 16 & 0xff) as f32 / 255.0, + ); + } + if let Some(x) = sec.get("Fog_End") { ret.fog_end = x.parse::<f32>()? / 10.0; } + if let Some(x) = sec.get("Mini_speed") { ret.mini_speed = x.parse::<f32>()? / 60.0; } + Ok(ret) + } +} + +pub struct Room { + pub config: Config, + pub shader: shader::Shader, + pub floor: texture::Texture, + pub wall: texture::Texture, + pub roof: texture::Texture, + pub art: texture::Texture, + pub credit: texture::Texture, + pub mini: texture::Texture, pub has_mini: bool, pub mini_frame: u64, + pub mini_pos: glam::Vec2, pub mini_dir: glam::Vec2, + pub interact: texture::Texture, pub has_interact: bool, + pub layer: texture::Texture, pub has_layer: bool, pub layer_frame: u64, + pub interact_mode: ui::Mode, + pub credit_mode: ui::Mode, + pub music: Option<(audio::Audio, audio::AudioPlayingHandle)>, + pub foot: Option<audio::Audio>, pub foot_countdown: u64, +} +impl Room { + pub fn new(ctx: &context::Context, shader: shader::Shader) -> Self { + Self { + config: Config::default(), + shader, + floor: texture::Texture::new_empty(ctx), + wall: texture::Texture::new_empty(ctx), + roof: texture::Texture::new_empty(ctx), + art: texture::Texture::new_empty(ctx), + credit: texture::Texture::new_empty(ctx), + mini: texture::Texture::new_empty(ctx), has_mini: false, mini_frame: 0, + mini_pos: glam::Vec2::new(4.0, 4.0), mini_dir: glam::Vec2::new(1.0, 0.0), + interact: texture::Texture::new_empty(ctx), has_interact: false, + layer: texture::Texture::new_empty(ctx), has_layer: false, layer_frame: 0, + interact_mode: ui::Mode::new(20), + credit_mode: ui::Mode::new(10), + music: None, + foot: None, + foot_countdown: 0, + } + } + fn load_file(base: impl AsRef<Path>, needle: &str) -> Erm<Vec<u8>> { + let base = base.as_ref(); + let uneedle = needle.to_uppercase(); + for mp in std::fs::read_dir(base)? { + if let Ok(p) = mp && let Some(onm) = p.path().file_name() && let Some(nm) = onm.to_str() { + if nm.to_uppercase().contains(&uneedle) { + return Ok(std::fs::read(p.path())?); + } + } + } + utils::erm_msg(&format!("failed to find {} in {}", needle, base.display())) + } + pub fn load_from_bytes( + &mut self, ctx: &context::Context, st: &mut state::State, + config: Option<&[u8]>, + floor: &[u8], wall: &[u8], roof: &[u8], art: &[u8], credit: &[u8], + mini: Option<&[u8]>, interact: Option<&[u8]>, layer: Option<&[u8]>, + music: Option<&[u8]>, foot: Option<&[u8]>, + ) -> Erm<()> { + self.config = Config::default(); + if let Some(bs) = config { + self.config = Config::from_room_ini(bs.to_owned())?; + } + self.floor.upload(ctx, floor); self.floor.set_repeat(ctx); + self.wall.upload(ctx, wall); self.wall.set_repeat(ctx); + self.roof.upload(ctx, roof); self.roof.set_repeat(ctx); + self.art.upload(ctx, art); + self.credit.upload(ctx, credit); + if let Some(bs) = mini { + self.mini.upload(ctx, &bs); + self.has_mini = true; + } else { self.has_mini = false; } + if let Some(bs) = interact { + self.interact.upload(ctx, &bs); + self.has_interact = true; + } else { self.has_interact = false; } + if let Some(bs) = layer { + self.layer.upload(ctx, &bs); + self.has_layer = true; + } else { self.has_layer = false; } + if let Some(bs) = music && let Some(audio) = st.audio.as_mut() { + let m = audio::Audio::new(&audio.ctx, &bs); + if let Some(handle) = m.play(&mut audio.ctx, Some((None, None))) { + self.music = Some((m, handle)) + } + } else { self.music = None; } + if let Some(bs) = foot && let Some(audio) = st.audio.as_mut() { + let m = audio::Audio::new(&audio.ctx, &bs); + self.foot = Some(m); + } else { self.foot = None; } + Ok(()) + } + pub fn load(&mut self, ctx: &context::Context, st: &mut state::State, dir: &str) -> Erm<()> { + let base = PathBuf::from(dir); + self.load_from_bytes(ctx, st, + Self::load_file(&base, "ROOM").ok().as_deref(), + &Self::load_file(&base, "FLOOR")?, + &Self::load_file(&base, "WALL")?, + &Self::load_file(&base, "ROOF")?, + &Self::load_file(&base, "ART")?, + &Self::load_file(&base, "CREDIT")?, + Self::load_file(&base, "MINI").ok().as_deref(), + Self::load_file(&base, "INTERACT").ok().as_deref(), + Self::load_file(&base, "LAYER").ok().as_deref(), + Self::load_file(&base, "MUSIC").ok().as_deref(), + Self::load_file(&base, "FOOT").ok().as_deref(), + )?; + Ok(()) + } + pub fn footstep(&mut self, _ctx: &context::Context, st: &mut state::State) -> Erm<()> { + if let Some(f) = &self.foot && let Some(audio) = st.audio.as_mut() { + if self.foot_countdown == 0 { + f.play(&mut audio.ctx, None); + self.foot_countdown = FOOTSTEP_TIME; + } else { + self.foot_countdown -= 1; + } + } + Ok(()) + } + pub fn render(&mut self, ctx: &context::Context, st: &mut state::State, yaw: f32) -> Erm<()> { + let scale = st.render_dims.x / 640.0; + st.projection = glam::Mat4::perspective_lh( + self.config.fov * PI / 180.0, + st.render_dims.x / st.render_dims.y, + 0.5, + 50.0, + ); + st.bind_3d(ctx, &self.shader); + self.shader.set_vec2(ctx, "texture_scale", + &glam::Vec2::new(self.config.texture_repeat, self.config.texture_repeat) + ); + self.shader.set_f32(ctx, "fog_distance", self.config.fog_end); + self.shader.set_vec3(ctx, "fog_color", &self.config.fog_color); + self.floor.bind(ctx); + self.shader.set_position_3d( + ctx, st, + &glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_x(PI / 2.0), + glam::Vec3::new(0.0, 0.0, 0.0), + ), + ); + st.mesh_square.render(ctx); + self.roof.bind(ctx); + self.shader.set_position_3d( + ctx, st, + &glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_x(3.0 * PI / 2.0), + glam::Vec3::new(0.0, self.config.room_height * PLANE_SIZE * 2.0, 0.0), + ), + ); + st.mesh_square.render(ctx); + self.wall.bind(ctx); + let wallpos = [ + glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_y(0.0), + glam::Vec3::new(0.0, PLANE_SIZE, PLANE_SIZE), + ), + glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_y(PI), + glam::Vec3::new(0.0, PLANE_SIZE, -PLANE_SIZE), + ), + glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_y(PI / 2.0), + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 0.0), + ), + glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(PLANE_SIZE, PLANE_SIZE, 1.0), + glam::Quat::from_rotation_y(3.0 * PI / 2.0), + glam::Vec3::new(-PLANE_SIZE, PLANE_SIZE, 0.0), + ), + ]; + for wp in wallpos { + self.shader.set_position_3d(ctx, st, &wp); + st.mesh_square.render(ctx); + } + self.shader.set_vec2(ctx, "texture_scale", &glam::Vec2::new(1.0, 1.0)); + self.art.bind(ctx); + self.shader.set_position_3d( + ctx, st, + &glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(1.0, 1.0, 1.0), + glam::Quat::from_rotation_y(yaw), + glam::Vec3::new(0.0, 1.0, 0.0), + ), + ); + st.mesh_square.render(ctx); + if self.has_mini { + self.mini.bind(ctx); + let xscale = 1.0 / 4.0; + let xoffset = xscale * self.mini_frame as f32; + if st.tick % 10 == 0 { + self.mini_frame += 1; + self.mini_frame %= 4; + } + self.shader.set_vec2(ctx, "texture_scale", &glam::Vec2::new(xscale, 1.0)); + self.shader.set_vec2(ctx, "texture_offset", &glam::Vec2::new(xoffset, 0.0)); + self.shader.set_position_3d( + ctx, st, + &glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(0.25, 0.25, 1.0), + glam::Quat::from_rotation_y(yaw), + glam::Vec3::new(self.mini_pos.x, 0.25, self.mini_pos.y), + ), + ); + st.mesh_square.render(ctx); + self.shader.set_vec2(ctx, "texture_scale", &glam::Vec2::new(1.0, 1.0)); + self.shader.set_vec2(ctx, "texture_offset", &glam::Vec2::new(0.0, 0.0)); + let newpos = self.mini_pos + self.config.mini_speed * self.mini_dir; + if newpos.x.abs() > PLANE_SIZE || newpos.y.abs() > PLANE_SIZE { + let angle = rand::thread_rng().gen_range(0..360) as f32 * PI / 180.0; + self.mini_dir = glam::Vec2::new(angle.cos(), angle.sin()); + } else { + self.mini_pos = newpos; + } + } + + ctx.clear_depth(); + self.shader.set_f32(ctx, "fog_distance", -1.0); + if self.has_layer { + st.bind_2d(ctx, &self.shader); + let xscale = 1.0 / self.config.layer_frames; + let xoffset = xscale * self.layer_frame as f32; + if st.tick % 10 == 0 { + self.layer_frame += 1; + self.layer_frame %= self.config.layer_frames as u64; + } + self.shader.set_vec2(ctx, "texture_scale", &glam::Vec2::new(xscale, 1.0)); + self.shader.set_vec2(ctx, "texture_offset", &glam::Vec2::new(xoffset, 0.0)); + self.layer.bind(ctx); + self.shader.set_position_2d( + ctx, st, + &glam::Vec2::new(0.0, 0.0), + &st.render_dims, + ); + st.mesh_square.render(ctx); + self.shader.set_vec2(ctx, "texture_scale", &glam::Vec2::new(1.0, 1.0)); + self.shader.set_vec2(ctx, "texture_offset", &glam::Vec2::new(0.0, 0.0)); + } + if self.has_interact { + st.bind_2d(ctx, &self.shader); + self.shader.set_f32(ctx, "opacity", self.interact_mode.progress(st.tick)); + self.interact.bind(ctx); + let iwidth = self.interact.width as f32 * scale; + let iheight = iwidth * (self.interact.height as f32 / self.interact.width as f32); + self.shader.set_position_2d( + ctx, st, + &glam::Vec2::new(0.0, 0.0), + &glam::Vec2::new(iwidth, iheight), + ); + st.mesh_square.render(ctx); + self.shader.set_f32(ctx, "opacity", 1.0); + } + st.bind_2d(ctx, &self.shader); + self.credit.bind(ctx); + let cwidth = self.credit.width as f32 * scale; + let cheight = cwidth * (self.credit.height as f32 / self.credit.width as f32); + self.shader.set_position_2d( + ctx, st, + &glam::Vec2::new(st.render_dims.x - cwidth, + utils::lerp( + st.render_dims.y, + st.render_dims.y - cheight, + self.credit_mode.progress(st.tick), + ), + ), + &glam::Vec2::new(cwidth, cheight), + ); + st.mesh_square.render(ctx); + Ok(()) + } +} |
