summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/camera.rs153
-rw-r--r--src/input.rs15
-rw-r--r--src/main.rs109
-rw-r--r--src/renderer/mod.rs10
4 files changed, 171 insertions, 116 deletions
diff --git a/src/camera.rs b/src/camera.rs
index 3de7ba7..576f12c 100644
--- a/src/camera.rs
+++ b/src/camera.rs
@@ -1,6 +1,9 @@
+use glam::{IVec2, Vec2};
+
use crate::{
config::CAMERA_MOVEMENT_SPEED,
input::{Input, InputManager},
+ sim::{entity::EntityId, sim_manager::SimManager},
};
#[repr(C)]
@@ -12,82 +15,122 @@ pub struct CameraUniform {
pub struct Camera {
pub zoom: f32,
- pub centre: (f32, f32),
- screen_size: (i32, i32),
+ pub centre: Vec2,
+ screen_size: IVec2,
}
impl Camera {
- fn scale(&self) -> (f32, f32) {
- let half_w = self.zoom * self.screen_size.0 as f32 / 2.0;
- let half_h = self.zoom * self.screen_size.1 as f32 / 2.0;
- (1.0 / half_w, -1.0 / half_h)
- }
-
- // xl, xu, yl, yu
- pub fn viewport_bounds_world(&self) -> (f32, f32, f32, f32) {
- let (xl, yl) = self.screen_position_to_world(0.0, 0.0);
- let (xu, yu) =
- self.screen_position_to_world(self.screen_size.0 as f32, self.screen_size.1 as f32);
- (xl, xu, yl, yu)
+ fn scale(&self) -> Vec2 {
+ let half = self.zoom * self.screen_size.as_vec2() / 2.0;
+ Vec2::new(1.0 / half.x, -1.0 / half.y)
}
- pub fn handle_camera_input(&mut self, input_manager: &InputManager, delta_time: f32) {
- // wasd movement
- let x: f32 = if input_manager.held(Input::CameraLeft) {
- -1.0
- } else if input_manager.held(Input::CameraRight) {
- 1.0
- } else {
- 0.0
- };
- let y: f32 = if input_manager.held(Input::CameraDown) {
- 1.0
- } else if input_manager.held(Input::CameraUp) {
- -1.0
- } else {
- 0.0
- };
-
- if x == 0.0 && y == 0.0 {
- return;
- }
-
- let magnitude = (x.powi(2) + y.powi(2)).sqrt();
- let adjusted_x = x / magnitude * self.zoom * CAMERA_MOVEMENT_SPEED * delta_time;
- let adjusted_y = y / magnitude * self.zoom * CAMERA_MOVEMENT_SPEED * delta_time;
-
- self.centre.0 += adjusted_x;
- self.centre.1 += adjusted_y;
+ // (lower, upper)
+ pub fn viewport_bounds_world(&self) -> (Vec2, Vec2) {
+ let lower = self.screen_position_to_world(Vec2::ZERO);
+ let upper = self.screen_position_to_world(self.screen_size.as_vec2());
+ (lower, upper)
}
- pub fn screen_position_to_world(&self, x: f32, y: f32) -> (f32, f32) {
- let (scale_x, scale_y) = self.scale();
-
- let ndc_x = x / self.screen_size.0 as f32 * 2.0 - 1.0;
- let world_x = ndc_x / scale_x + self.centre.0;
- let ndc_y = y / self.screen_size.1 as f32 * 2.0 - 1.0;
- let world_y = ndc_y / -scale_y + self.centre.1;
+ pub fn screen_position_to_world(&self, pos: Vec2) -> Vec2 {
+ let scale = self.scale();
+ let ndc = pos / self.screen_size.as_vec2() * 2.0 - 1.0;
+ let world = Vec2::new(
+ ndc.x / scale.x + self.centre.x,
+ ndc.y / -scale.y + self.centre.y,
+ );
- (world_x, world_y)
+ world
}
pub fn to_uniform(&self) -> CameraUniform {
- let (scale_x, scale_y) = self.scale();
CameraUniform {
- scale: [scale_x, scale_y],
- centre: [self.centre.0, self.centre.1],
+ scale: self.scale().to_array(),
+ centre: self.centre.to_array(),
}
}
- pub fn resize(&mut self, screen_size: (i32, i32)) {
+ pub fn resize(&mut self, screen_size: IVec2) {
self.screen_size = screen_size;
}
- pub fn new(screen_size: (i32, i32)) -> Self {
+ pub fn new(screen_size: IVec2) -> Self {
Camera {
zoom: 0.12,
- centre: (0.0, 0.0),
+ centre: Vec2::ZERO,
screen_size,
}
}
}
+
+pub enum CameraControllerMode {
+ Free,
+ TrackEntity(EntityId),
+}
+
+pub struct CameraController {
+ camera: Camera,
+ mode: CameraControllerMode,
+}
+
+impl CameraController {
+ pub fn track_entity(&mut self, entity_id: EntityId) {
+ self.mode = CameraControllerMode::TrackEntity(entity_id);
+ }
+
+ pub fn free_camera(&mut self) {
+ self.mode = CameraControllerMode::Free;
+ }
+
+ pub fn camera(&self) -> &Camera {
+ &self.camera
+ }
+
+ pub fn camera_mut(&mut self) -> &mut Camera {
+ &mut self.camera
+ }
+
+ pub fn update(&mut self, input_manager: &InputManager, sim: &SimManager, delta_time: f32) {
+ match self.mode {
+ CameraControllerMode::Free => {
+ let x: f32 = if input_manager.held(Input::CameraLeft) {
+ -1.0
+ } else if input_manager.held(Input::CameraRight) {
+ 1.0
+ } else {
+ 0.0
+ };
+ let y: f32 = if input_manager.held(Input::CameraDown) {
+ 1.0
+ } else if input_manager.held(Input::CameraUp) {
+ -1.0
+ } else {
+ 0.0
+ };
+
+ if x == 0.0 && y == 0.0 {
+ return;
+ }
+
+ let magnitude = (x.powi(2) + y.powi(2)).sqrt();
+ let adjusted_x =
+ x / magnitude * self.camera.zoom * CAMERA_MOVEMENT_SPEED * delta_time;
+ let adjusted_y =
+ y / magnitude * self.camera.zoom * CAMERA_MOVEMENT_SPEED * delta_time;
+
+ self.camera.centre += Vec2::new(adjusted_x, adjusted_y);
+ }
+ CameraControllerMode::TrackEntity(entity_id) => {
+ if let Some(entity) = sim.entities.get(&entity_id) {
+ let (position, _) = entity.data._transform(&sim.rb_manager).unwrap();
+ self.camera.centre = position;
+ }
+ }
+ }
+ }
+
+ pub fn new(screen_size: IVec2, mode: CameraControllerMode) -> Self {
+ let camera = Camera::new(screen_size);
+ CameraController { camera, mode }
+ }
+}
diff --git a/src/input.rs b/src/input.rs
index e795a61..108514e 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -14,6 +14,8 @@ pub enum Input {
Down,
Right,
+ // camera
+ FreeCamera,
CameraUp,
CameraLeft,
CameraDown,
@@ -39,18 +41,19 @@ pub enum Input {
Action6,
}
-const INPUT_VAR_LEN: usize = 21;
+const INPUT_VAR_LEN: usize = 22;
const KEYMAP: [(KeyCode, Input); INPUT_VAR_LEN] = [
(KeyCode::KeyW, Input::Up),
(KeyCode::KeyA, Input::Left),
(KeyCode::KeyS, Input::Down),
(KeyCode::KeyD, Input::Right),
+ (KeyCode::KeyZ, Input::FreeCamera),
(KeyCode::ArrowUp, Input::CameraUp),
(KeyCode::ArrowLeft, Input::CameraLeft),
(KeyCode::ArrowDown, Input::CameraDown),
(KeyCode::ArrowRight, Input::CameraRight),
- (KeyCode::Space, Input::Pause),
+ (KeyCode::KeyU, Input::Pause),
(KeyCode::KeyX, Input::Step),
(KeyCode::KeyC, Input::ClearGrid),
(KeyCode::KeyV, Input::ClearEntities),
@@ -108,14 +111,14 @@ impl InputManager {
}
}
WindowEvent::CursorMoved { position, .. } => {
- let (wp_x, wp_y) =
- camera.screen_position_to_world(position.x as f32, position.y as f32);
+ let wp = camera
+ .screen_position_to_world(Vec2::new(position.x as f32, position.y as f32));
let ((cx, cy), (lx, ly)) =
- CellManager::split_game_position(wp_x.round() as i32, wp_y.round() as i32);
+ CellManager::split_game_position(wp.x.round() as i32, wp.y.round() as i32);
self.screen_mouse_pos = Vec2::new(position.x as f32, position.y as f32);
- self.world_mouse_pos = Vec2::new(wp_x, wp_y);
+ self.world_mouse_pos = wp;
self.chunk_mouse_pos = IVec2::new(cx, cy);
self.local_mouse_pos = IVec2::new(lx as i32, ly as i32);
}
diff --git a/src/main.rs b/src/main.rs
index 4d62f8c..9455ac6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,6 +9,7 @@ mod sprite_loader;
mod vfx;
use futures::executor;
+use glam::IVec2;
use std::{collections::VecDeque, sync::Arc, time::Instant};
use winit::{
application::ApplicationHandler,
@@ -18,7 +19,7 @@ use winit::{
};
use crate::{
- camera::Camera,
+ camera::{Camera, CameraController},
config::WINDOW_TITLE,
content::{
entities::{
@@ -35,7 +36,7 @@ use crate::{
},
proc_gen::TilesetWorldGenerator,
renderer::RendererState,
- sim::{entity::EntityDef, rb_manager::DebugRenderMode, sim_manager::SimManager},
+ sim::{rb_manager::DebugRenderMode, sim_manager::SimManager},
vfx::VfxManager,
};
@@ -66,9 +67,9 @@ struct App {
// game
input_manager: InputManager,
- camera: Option<Camera>,
- vfx_manager: Option<VfxManager>,
- sim_manager: Option<SimManager>,
+ camera_controller: Option<CameraController>,
+ vfx_manager: VfxManager,
+ sim_manager: SimManager,
world_generator: TilesetWorldGenerator,
// renderer
@@ -84,43 +85,47 @@ impl App {
// delta time is the real seconds elapsed since the last time this was called
fn update(&mut self, delta_time: f32) {
// apply inputs
- if let Some(camera) = &mut self.camera {
- camera.handle_camera_input(&self.input_manager, delta_time)
+ if let Some(camera_controller) = &mut self.camera_controller {
+ camera_controller.update(&self.input_manager, &self.sim_manager, delta_time);
}
- if let Some(sim) = &mut self.sim_manager
- && let Some(vfx_manager) = &mut self.vfx_manager
- {
- // --TEST SPAWNING--
- if self.input_manager.pressed(Input::Action1) {
- sim.create_entity(entity_cube_def(
- self.input_manager.world_mouse_pos,
- self.config.dropper_material,
- ));
- }
-
- if self.input_manager.pressed(Input::Grenade) {
- sim.create_entity(entity_grenade_def(self.input_manager.world_mouse_pos, 3.0));
- }
+ // --TEST SPAWNING--
+ if self.input_manager.pressed(Input::Action1) {
+ self.sim_manager.create_entity(entity_cube_def(
+ self.input_manager.world_mouse_pos,
+ self.config.dropper_material,
+ ));
+ }
- if self.input_manager.pressed(Input::Tnt) {
- sim.create_entity(entity_tnt_def(self.input_manager.world_mouse_pos));
- }
+ if self.input_manager.pressed(Input::Grenade) {
+ self.sim_manager
+ .create_entity(entity_grenade_def(self.input_manager.world_mouse_pos, 3.0));
+ }
- if self.input_manager.pressed(Input::Action5) {
- sim.create_entity(entity_wizard_def(self.input_manager.world_mouse_pos));
- }
+ if self.input_manager.pressed(Input::Tnt) {
+ self.sim_manager
+ .create_entity(entity_tnt_def(self.input_manager.world_mouse_pos));
+ }
- if self.input_manager.pressed(Input::Action3) {
- sim.create_entity(entity_bullet_emitter_def(
- self.input_manager.world_mouse_pos,
- 3.0,
- ));
- }
+ if self.input_manager.pressed(Input::Action5) {
+ self.sim_manager
+ .create_entity(entity_wizard_def(self.input_manager.world_mouse_pos));
+ }
- sim.update(vfx_manager, &self.config, &self.input_manager, delta_time);
- self.input_manager.reset_for_frame();
+ if self.input_manager.pressed(Input::Action3) {
+ self.sim_manager.create_entity(entity_bullet_emitter_def(
+ self.input_manager.world_mouse_pos,
+ 3.0,
+ ));
}
+
+ self.sim_manager.update(
+ &mut self.vfx_manager,
+ &self.config,
+ &self.input_manager,
+ delta_time,
+ );
+ self.input_manager.reset_for_frame();
}
}
@@ -141,10 +146,10 @@ impl Default for App {
input_manager: InputManager::new(),
- camera: None,
+ camera_controller: None,
- vfx_manager: Some(VfxManager::new()),
- sim_manager: Some(SimManager::new()),
+ vfx_manager: VfxManager::new(),
+ sim_manager: SimManager::new(),
world_generator: TilesetWorldGenerator::new(
"assets/tilesets/tileset1",
Box::new(MinesBiome::new()),
@@ -177,7 +182,10 @@ impl ApplicationHandler for App {
self.renderer_state = Some(executor::block_on(RendererState::new(window.clone())));
let size = window.inner_size();
- self.camera = Some(Camera::new((size.width as i32, size.height as i32)));
+ self.camera_controller = Some(CameraController::new(
+ IVec2::new(size.width as i32, size.height as i32),
+ camera::CameraControllerMode::Free,
+ ));
}
fn window_event(
@@ -196,17 +204,20 @@ impl ApplicationHandler for App {
}
}
- if let Some(camera) = &self.camera {
- self.input_manager.apply_event(&event, camera);
+ if let Some(camera_controller) = &self.camera_controller {
+ self.input_manager
+ .apply_event(&event, camera_controller.camera());
}
match event {
WindowEvent::Resized(size) => {
if let Some(renderer_state) = &mut self.renderer_state
- && let Some(camera) = &mut self.camera
+ && let Some(camera_controller) = &mut self.camera_controller
{
renderer_state.resize(size.width, size.height);
- camera.resize((size.width as i32, size.height as i32));
+ camera_controller
+ .camera_mut()
+ .resize(IVec2::new(size.width as i32, size.height as i32));
}
}
WindowEvent::CloseRequested => {
@@ -236,21 +247,19 @@ impl ApplicationHandler for App {
self.update(delta_time);
if let Some(renderer_state) = &mut self.renderer_state
- && let Some(sim) = &mut self.sim_manager
- && let Some(vfx) = &mut self.vfx_manager
- && let Some(camera) = &mut self.camera
+ && let Some(camera_controller) = &mut self.camera_controller
{
renderer_state.render(
- sim,
- vfx,
- camera,
+ &mut self.sim_manager,
+ &self.vfx_manager,
+ camera_controller.camera_mut(),
&mut self.config,
&self.diagnostics,
&self.input_manager,
&self.world_generator,
);
- vfx.after_render(delta_time);
+ self.vfx_manager.after_render(delta_time);
}
}
_ => {}
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index b806b13..2deb278 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -392,7 +392,7 @@ impl RendererState {
let entity_capacity = 2048;
let instance_buffer = create_instance_buffer(&device, CHUNK_SLOTS + entity_capacity);
- let cell_buffer = create_cell_buffer(&device, entity_capacity + CHUNK_SLOTS );
+ let cell_buffer = create_cell_buffer(&device, entity_capacity + CHUNK_SLOTS);
let instance_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
@@ -920,11 +920,11 @@ impl RendererState {
{
puffin::profile_scope!("Build instances");
- let (xl, xu, yl, yu) = camera.viewport_bounds_world();
+ let (lower, upper) = camera.viewport_bounds_world();
let ((cxl, cyl), _) =
- CellManager::split_game_position(xl.floor() as i32, yl.floor() as i32);
+ CellManager::split_game_position(lower.x.floor() as i32, lower.y.floor() as i32);
let ((cxu, cyu), _) =
- CellManager::split_game_position(xu.floor() as i32, yu.floor() as i32);
+ CellManager::split_game_position(upper.x.floor() as i32, upper.y.floor() as i32);
let half_size = [CHUNK_SIZE as f32 / 2.0, CHUNK_SIZE as f32 / 2.0];
let dims = [CHUNK_SIZE as u32, CHUNK_SIZE as u32];
@@ -985,7 +985,7 @@ impl RendererState {
self.instance_buffer =
create_instance_buffer(&self.device, self.entity_capacity + CHUNK_SLOTS);
self.cell_buffer =
- create_cell_buffer(&self.device, ((CHUNK_SLOTS + self.entity_capacity)));
+ create_cell_buffer(&self.device, CHUNK_SLOTS + self.entity_capacity);
}
self.queue