use std::time::Instant; use cgmath::{Deg, Euler, Quaternion, vec3}; use glyph_brush::GlyphBrush; use winit::event::Event; use level::{load_level, save_level}; use player::Player; use crate::game::entities::{FpsCounter, UiQuad}; use crate::text::create_brush; use crate::{config::LogConfig, vulkan}; use crate::input::InputState; use crate::vulkan::{Game, MeshHandle, TextVertex, Vertex, VulkanRenderer}; use crate::vulkan::gameobject::{GameObject, GameObjectHandle, Updatable}; use crate::vulkan::mesh; use crate::vulkan::pipelines::vs::ty::ObjectUniformData; pub mod player; mod level; mod entities; pub struct GameState { pub paused: bool, pub brush: GlyphBrush>, pub test_str: String, } impl GameState { fn new() -> GameState { GameState { brush: create_brush(), paused: false, test_str: "".to_string(), } } } pub struct TestGame { pub input: InputState, pub player: Player, pub game_objects: Vec, pub log_config: LogConfig, pub texture_index_counter: usize, pub last_time: f32, pub components: Vec>, pub game_state: GameState, } impl Game for TestGame { fn get_game_objects(&self) -> &Vec { &self.game_objects } fn on_window_event(self: &mut Self, event: &Event<()>) { self.input.on_window_event(event); } fn update(self: &mut Self, renderer: &mut VulkanRenderer) -> ObjectUniformData { let precise_start = Instant::now(); // Input and timing self.input.frame_start(); let time = (renderer.game_data.start_time.elapsed().unwrap().as_micros() as f64 / 1000000.0) as f32; let frame_time = time - self.last_time; // Component update let input = &self.input; let objs = &mut self.game_objects; let components = &mut self.components; let paused = self.game_state.paused; let state = &mut self.game_state; if !paused { components.iter_mut().for_each(|component| { component.update(frame_time, &input, state, objs, renderer); }); self.player.update(frame_time, &input, state, objs, renderer); } // User interaction if self.input.button_just_released("quit") { renderer.game_data.shutdown = true; } if self.input.button_just_pressed("reload_shaders") { renderer.recreate_swapchain = true; } if self.input.button_just_pressed("quicksave") { save_level("levels/test.lvl", self, renderer).unwrap(); } if self.input.button_just_pressed("quickload") { self.clear_level(renderer); load_level("levels/test.lvl", self, renderer).unwrap(); } if self.input.button_just_pressed("test") { self.game_state.paused = !self.game_state.paused; } for char in self.input.typed_characters.iter() { match char { '\u{8}' => { self.game_state.test_str.pop(); }, c => { self.game_state.test_str.push(*c); }, } } // Custom game object stuff let light_pos = vec3(2.0, 0.5, 2.0); // End frame self.last_time = time; self.input.frame_end(); let precise_duration = precise_start.elapsed().as_micros(); renderer.game_data.update_perf_counters[renderer.game_data.performance_counter_index] = precise_duration; ObjectUniformData { view: self.player.camera.view.into(), projection: self.player.camera.proj.into(), ortho_projection: self.player.camera.ortho_proj.into(), time, light_position: light_pos.into(), light_directional_rotation: [45.0, 45.0, 0.0], camera_position: self.player.camera.position.into(), _dummy0: [0; 12], _dummy1: [0; 4], _dummy2: [0; 4], } } } impl TestGame { pub fn new(toml_path: &str, log_config: LogConfig) -> TestGame { TestGame { input: InputState::new(toml_path, log_config), player: Player::new(3., 30.), game_objects: vec![], log_config, texture_index_counter: 0, last_time: 0.0, components: vec![], game_state: GameState::new() } } pub fn game_start(self: &mut Self, renderer: &mut VulkanRenderer) { load_level("levels/test.lvl", self, renderer).unwrap(); let fps = FpsCounter::new(self, renderer); self.components.push(Box::new(fps)); let test_quad = UiQuad::new(self, renderer); self.components.push(Box::new(test_quad)); println!("Game loaded!"); } pub fn offset_texture_id(&mut self, local_tex_id: Option) -> usize { match local_tex_id { Some(local_id) => local_id + self.texture_index_counter, None => 0, } } pub fn load_gltf(&mut self, renderer: &mut VulkanRenderer, gltf_path: &str) -> Vec { let mut mesh_handles = Vec::new(); // Load file let (meshes, document) = mesh::load_mesh::(gltf_path, self.log_config.mesh_load_info).unwrap(); for cpu_mesh in meshes.into_iter() { // Convert file texture id to game texture id let diffuse_id = self.offset_texture_id(cpu_mesh.local_texture_index); let normal_id = self.offset_texture_id(cpu_mesh.local_normal_map_index); // Upload mesh let mesh_id = renderer.upload_mesh(cpu_mesh, Some(gltf_path.to_string())); let mesh_handle = MeshHandle { index: mesh_id, textures: vec![diffuse_id, normal_id], original_path: Some(gltf_path.to_string()), pipeline_index: 0 }; mesh_handles.push(mesh_handle); } for doc_image in document.images() { let texture_start_time = Instant::now(); let texture = vulkan::dds::upload_texture_from_file(&format!("models/textures/{}.dds", doc_image.name().unwrap()), renderer).unwrap(); renderer.game_data.textures.push(texture); self.texture_index_counter += 1; if self.log_config.mesh_load_info { println!("Uploading texture took {:?}ms", texture_start_time.elapsed().as_millis()); } } mesh_handles } pub fn add_game_object(&mut self, renderer: &mut VulkanRenderer, mesh: MeshHandle) -> GameObjectHandle { let mut obj = GameObject::new(mesh); obj.init_descriptor_sets(renderer); self.game_objects.push(obj); self.game_objects.len() - 1 } pub fn clear_level(&mut self, renderer: &mut VulkanRenderer) { self.game_objects.clear(); self.texture_index_counter = 0; renderer.clear_all(); } } pub fn _print_quat_as_euler(quat: Quaternion) { let euler = Euler::from(quat); print!("({:?},{:?},{:?})", Deg::from(euler.x), Deg::from(euler.y), Deg::from(euler.z)); }