180 lines
4.9 KiB
Rust
180 lines
4.9 KiB
Rust
#![feature(duration_constants)]
|
|
#![allow(clippy::new_without_default, clippy::let_unit_value)]
|
|
|
|
use std::{process::ExitCode, sync::Arc, time::Instant};
|
|
|
|
use error::Error;
|
|
use glam::Vec3;
|
|
use render::{
|
|
asset::{AssetLoader, TextureLoadStage},
|
|
Renderer,
|
|
};
|
|
use winit::{
|
|
application::ApplicationHandler,
|
|
dpi::PhysicalSize,
|
|
event::{DeviceEvent, DeviceId, StartCause, WindowEvent},
|
|
event_loop::{ActiveEventLoop, EventLoop},
|
|
window::{Window, WindowId},
|
|
};
|
|
use world::{Chunk, ChunkGenerator, NoiseChunkGenerator, World};
|
|
|
|
pub mod error;
|
|
pub mod render;
|
|
pub mod world;
|
|
|
|
pub struct Engine {
|
|
window: Option<Arc<Window>>,
|
|
renderer: Option<Renderer>,
|
|
assets: Option<AssetLoader<TextureLoadStage>>,
|
|
world: Option<World>,
|
|
camera_position: Vec3,
|
|
generator: Box<dyn ChunkGenerator>,
|
|
start: Instant,
|
|
}
|
|
|
|
impl Engine {
|
|
pub fn ensure_renderer(&mut self, event_loop: &ActiveEventLoop) -> Result<(), Error> {
|
|
if self.window.is_none() {
|
|
let assets = self.assets.take().expect("asset loader");
|
|
let window_attributes = Window::default_attributes()
|
|
.with_resizable(false)
|
|
.with_inner_size(PhysicalSize::new(800, 600));
|
|
|
|
let window = Arc::new(event_loop.create_window(window_attributes)?);
|
|
let render = Renderer::from_window(window.clone(), assets)?;
|
|
|
|
self.window = Some(window);
|
|
self.renderer = Some(render);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl ApplicationHandler for Engine {
|
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
|
if let Err(error) = self.ensure_renderer(event_loop) {
|
|
log::error!("Renderer setup error: {error}");
|
|
event_loop.exit();
|
|
}
|
|
}
|
|
|
|
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
|
|
let _ = event_loop;
|
|
log::info!("Exiting");
|
|
self.renderer = None;
|
|
}
|
|
|
|
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
|
|
let _ = event_loop;
|
|
}
|
|
|
|
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
|
|
let _ = event_loop;
|
|
let _ = cause;
|
|
}
|
|
|
|
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: ()) {
|
|
let _ = event_loop;
|
|
let _ = event;
|
|
}
|
|
|
|
fn window_event(
|
|
&mut self,
|
|
event_loop: &ActiveEventLoop,
|
|
window_id: WindowId,
|
|
event: WindowEvent,
|
|
) {
|
|
let _ = window_id;
|
|
|
|
match event {
|
|
WindowEvent::CloseRequested => {
|
|
log::info!("Close requested");
|
|
event_loop.exit();
|
|
}
|
|
WindowEvent::Resized(size) => {
|
|
log::info!("Window resized: {size:?}");
|
|
if let Some(render) = self.renderer.as_mut() {
|
|
render.set_swapchain_dirty();
|
|
}
|
|
}
|
|
WindowEvent::RedrawRequested => {
|
|
if let (Some(render), Some(world)) = (self.renderer.as_mut(), self.world.as_mut()) {
|
|
let delta = self.start.elapsed();
|
|
let dt = delta.as_secs_f64();
|
|
|
|
self.camera_position = Vec3::new(
|
|
(dt.cos() * 32.0) as f32 + (Chunk::SIZE / 2) as f32,
|
|
48.0,
|
|
(dt.sin() * 32.0) as f32 + (Chunk::SIZE / 2) as f32,
|
|
);
|
|
|
|
world.update_with_camera(self.camera_position, &mut *self.generator);
|
|
|
|
if let Err(error) = render.render(self.camera_position, world) {
|
|
log::error!("Render error: {error}");
|
|
event_loop.exit();
|
|
}
|
|
}
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
|
|
fn device_event(
|
|
&mut self,
|
|
event_loop: &ActiveEventLoop,
|
|
device_id: DeviceId,
|
|
event: DeviceEvent,
|
|
) {
|
|
let _ = event_loop;
|
|
let _ = device_id;
|
|
let _ = event;
|
|
}
|
|
|
|
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
|
|
let _ = event_loop;
|
|
|
|
if let Some(window) = self.window.as_ref() {
|
|
window.request_redraw();
|
|
}
|
|
}
|
|
|
|
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
|
|
let _ = event_loop;
|
|
}
|
|
}
|
|
|
|
fn run() -> Result<(), Error> {
|
|
let loader = AssetLoader::new();
|
|
let (loader, block_registry) = loader.load_block_definitions()?;
|
|
let world = World::new(block_registry);
|
|
|
|
let event_loop = EventLoop::new()?;
|
|
let mut engine = Engine {
|
|
window: None,
|
|
renderer: None,
|
|
assets: Some(loader),
|
|
world: Some(world),
|
|
camera_position: Vec3::ZERO,
|
|
generator: Box::new(NoiseChunkGenerator::from_seed(1234)),
|
|
start: Instant::now(),
|
|
};
|
|
|
|
event_loop.run_app(&mut engine)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> ExitCode {
|
|
env_logger::init();
|
|
match run() {
|
|
Ok(()) => ExitCode::SUCCESS,
|
|
Err(error) => {
|
|
log::error!("Exited with error: {error}");
|
|
ExitCode::FAILURE
|
|
}
|
|
}
|
|
}
|
|
|