221 lines
7.1 KiB
Rust
221 lines
7.1 KiB
Rust
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<Vec<TextVertex>>,
|
|
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<GameObject>,
|
|
pub log_config: LogConfig,
|
|
pub texture_index_counter: usize,
|
|
pub last_time: f32,
|
|
pub components: Vec<Box<dyn Updatable>>,
|
|
pub game_state: GameState,
|
|
}
|
|
|
|
impl Game for TestGame {
|
|
fn get_game_objects(&self) -> &Vec<GameObject> {
|
|
&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>) -> 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<MeshHandle> {
|
|
let mut mesh_handles = Vec::new();
|
|
|
|
// Load file
|
|
let (meshes, document) = mesh::load_mesh::<Vertex>(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<f32>) {
|
|
let euler = Euler::from(quat);
|
|
print!("({:?},{:?},{:?})", Deg::from(euler.x), Deg::from(euler.y), Deg::from(euler.z));
|
|
}
|