#![allow(dead_code, unused_variables)] 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, mesh_cube: mesh::Mesh, texture_test: texture::Texture, } impl Assets { fn new(ctx: &context::Context) -> Self { Self { font: font::Bitmap::default(ctx), 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, 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 { HashMap::from_iter(vec![ ("mrbeast".to_owned(), audio::Audio::new(&actx, include_bytes!("assets/audio/mrbeast.mp3"))), ]) } 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(); 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(()) } }