rts camera
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -1382,13 +1382,6 @@ dependencies = [
|
||||
"wayland-client",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "camera_system"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.90"
|
||||
@@ -3223,7 +3216,6 @@ dependencies = [
|
||||
"bevy",
|
||||
"bevy-inspector-egui 0.23.4",
|
||||
"bevy_rapier3d",
|
||||
"camera_system",
|
||||
"iyes_perf_ui",
|
||||
"noise 0.8.2",
|
||||
"rayon",
|
||||
|
||||
@@ -3,8 +3,7 @@ resolver = "2"
|
||||
members = [
|
||||
"game/main",
|
||||
"engine/world_generation",
|
||||
"game/camera_system"
|
||||
, "engine/asset_loader"]
|
||||
"engine/asset_loader"]
|
||||
|
||||
# Enable a small amount of optimization in debug mode
|
||||
[profile.dev]
|
||||
|
||||
@@ -86,6 +86,20 @@ impl HexCoord {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn from_world_pos(world_pos: Vec3) -> Self {
|
||||
let offset = world_pos.z / (OUTER_RADIUS * 3.);
|
||||
let mut x = world_pos.x / (INNER_RADIUS * 2.);
|
||||
let mut z = -x;
|
||||
z -= offset;
|
||||
x -= offset;
|
||||
|
||||
let i_x = x.round() as i32;
|
||||
let i_z = (-x - z).round() as i32;
|
||||
let offset_pos = IVec2::new(i_x + i_z / 2, i_z);
|
||||
|
||||
return Self::from_offset(offset_pos);
|
||||
}
|
||||
|
||||
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool {
|
||||
let off = self.to_offset();
|
||||
if off.x < 0 || off.y < 0 {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
[package]
|
||||
name = "camera_system"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.13.1"
|
||||
@@ -12,6 +12,5 @@ bevy-inspector-egui = "0.23.4"
|
||||
iyes_perf_ui = "0.2.3"
|
||||
noise = "0.8.2"
|
||||
world_generation ={path="../../engine/world_generation"}
|
||||
camera_system={path = "../camera_system"}
|
||||
bevy_rapier3d = { version = "0.25.0", features = [ "simd-stable", "debug-render-3d","parallel" ] }
|
||||
rayon = "1.10.0"
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
use crate::prelude::PhosCamera;
|
||||
use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin};
|
||||
use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
|
||||
use bevy::pbr::ScreenSpaceAmbientOcclusionBundle;
|
||||
use bevy::prelude::*;
|
||||
use bevy::window::CursorGrabMode;
|
||||
use prelude::{CameraBounds, PhosCameraTargets};
|
||||
use bevy_rapier3d::plugin::RapierContext;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
use world_generation::prelude::Map;
|
||||
|
||||
pub mod prelude;
|
||||
use super::components::*;
|
||||
|
||||
pub struct PhosCameraPlugin;
|
||||
|
||||
impl Plugin for PhosCameraPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<PhosCamera>();
|
||||
|
||||
app.add_systems(PreStartup, setup);
|
||||
|
||||
app.add_systems(Update, (rts_camera_system, apply_camera_height).chain());
|
||||
app.add_systems(Update, rts_camera_system);
|
||||
app.add_systems(PostUpdate, limit_camera_bounds);
|
||||
//Free Cam
|
||||
//app.add_systems(Update, (grab_mouse, (update_camera, update_camera_mouse).chain()));
|
||||
@@ -27,15 +30,10 @@ fn setup(mut commands: Commands, mut msaa: ResMut<Msaa>) {
|
||||
commands
|
||||
.spawn((
|
||||
Camera3dBundle {
|
||||
transform: Transform::from_xyz(0., 30., 0.)
|
||||
.with_rotation(Quat::from_axis_angle(Vec3::Y, (-90 as f32).to_radians())),
|
||||
..default()
|
||||
},
|
||||
PhosCamera {
|
||||
speed: 100.,
|
||||
zoom_speed: 20.,
|
||||
transform: Transform::from_xyz(0., 30., 0.).looking_to(Vec3::Z, Vec3::Y),
|
||||
..default()
|
||||
},
|
||||
PhosCamera::default(),
|
||||
PhosCameraTargets::default(),
|
||||
))
|
||||
.insert(ScreenSpaceAmbientOcclusionBundle::default())
|
||||
@@ -128,12 +126,14 @@ fn grab_mouse(mut windows: Query<&mut Window>, mouse: Res<ButtonInput<MouseButto
|
||||
|
||||
fn rts_camera_system(
|
||||
mut cam_query: Query<(&mut Transform, &PhosCamera, &mut PhosCameraTargets)>,
|
||||
mut wheel: EventReader<MouseWheel>,
|
||||
key: Res<ButtonInput<KeyCode>>,
|
||||
time: Res<Time>,
|
||||
mut wheel: EventReader<MouseWheel>,
|
||||
heightmap: Res<Map>,
|
||||
) {
|
||||
let (mut cam, cam_cfg, mut cam_targets) = cam_query.single_mut();
|
||||
let mut cam_move = Vec3::ZERO;
|
||||
let mut cam_pos = cam.translation;
|
||||
|
||||
if key.pressed(KeyCode::KeyA) {
|
||||
cam_move.x = 1.;
|
||||
@@ -147,30 +147,75 @@ fn rts_camera_system(
|
||||
cam_move.z = -1.;
|
||||
}
|
||||
|
||||
let fwd = cam.forward();
|
||||
let fwd_quat = Quat::from_rotation_arc(Vec3::Z, fwd.into());
|
||||
cam_move = fwd_quat.mul_vec3(cam_move.normalize_or_zero()) * cam_cfg.speed * time.delta_seconds();
|
||||
if key.pressed(KeyCode::ShiftLeft) {
|
||||
cam_move = cam_move.normalize_or_zero() * cam_cfg.speed * time.delta_seconds() * 2.;
|
||||
} else {
|
||||
cam_move = cam_move.normalize_or_zero() * cam_cfg.speed * time.delta_seconds();
|
||||
}
|
||||
|
||||
cam_pos -= cam_move;
|
||||
|
||||
let mut scroll = 0.0;
|
||||
for e in wheel.read() {
|
||||
match e.unit {
|
||||
MouseScrollUnit::Line => cam_targets.height -= e.y * 20.,
|
||||
MouseScrollUnit::Pixel => cam_targets.height -= e.y,
|
||||
MouseScrollUnit::Line => scroll += e.y * 5.,
|
||||
MouseScrollUnit::Pixel => scroll += e.y,
|
||||
}
|
||||
}
|
||||
|
||||
cam_targets.height = cam_targets.height.clamp(cam_cfg.min_height, cam_cfg.max_height);
|
||||
cam_targets.height -= scroll;
|
||||
if cam_targets.height > cam_cfg.max_height {
|
||||
cam_targets.height = cam_cfg.max_height;
|
||||
}
|
||||
|
||||
cam.translation += cam_move;
|
||||
let tile_under = HexCoord::from_world_pos(cam.translation);
|
||||
let neighbors = heightmap.get_neighbors(&tile_under);
|
||||
let mut ground_height = heightmap.sample_height(&tile_under);
|
||||
for n in neighbors {
|
||||
if let Some(h) = n {
|
||||
if h > ground_height {
|
||||
ground_height = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let min_height = ground_height + cam_cfg.min_height;
|
||||
|
||||
if min_height != cam_targets.last_height {
|
||||
cam_targets.last_height = min_height;
|
||||
cam_targets.anim_time = 0.;
|
||||
cam_targets.rotate_time = 0.;
|
||||
}
|
||||
|
||||
if scroll != 0. {
|
||||
cam_targets.anim_time = 0.;
|
||||
cam_targets.rotate_time = 0.;
|
||||
if cam_targets.height < min_height {
|
||||
cam_targets.height = min_height;
|
||||
}
|
||||
}
|
||||
|
||||
let desired_height = if cam_targets.height < min_height {
|
||||
min_height
|
||||
} else {
|
||||
cam_targets.height
|
||||
};
|
||||
if cam_targets.anim_time < 1. {
|
||||
cam_targets.anim_time += time.delta_seconds() * cam_cfg.zoom_speed;
|
||||
cam_targets.anim_time = cam_targets.anim_time.min(1.);
|
||||
}
|
||||
cam_pos.y = f32::lerp(cam_pos.y, desired_height, cam_targets.anim_time);
|
||||
let t = cam_pos.y.remap(cam_cfg.min_height, cam_cfg.max_height, 0., 1.);
|
||||
|
||||
if cam_targets.rotate_time < 1. {
|
||||
cam_targets.rotate_time += time.delta_seconds();
|
||||
cam_targets.rotate_time = cam_targets.rotate_time.min(1.);
|
||||
}
|
||||
let angle = cam_cfg.min_angle.lerp(cam_cfg.max_angle, t);
|
||||
let rot = Quat::from_axis_angle(Vec3::X, -angle);
|
||||
cam.rotation = rot;
|
||||
|
||||
cam.translation = cam_pos;
|
||||
}
|
||||
|
||||
fn apply_camera_height(mut cam_query: Query<(&mut Transform, &PhosCamera, &mut PhosCameraTargets)>, time: Res<Time>) {
|
||||
let (mut cam_t, cam_cfg, targets) = cam_query.single_mut();
|
||||
|
||||
let movement = (cam_t.translation.y - targets.height) * time.delta_seconds();
|
||||
|
||||
cam_t.translation.y -= movement;
|
||||
}
|
||||
|
||||
fn limit_camera_bounds(mut cam_query: Query<(&mut Transform, &CameraBounds)>) {
|
||||
|
||||
}
|
||||
fn limit_camera_bounds(mut cam_query: Query<(&mut Transform, &CameraBounds)>) {}
|
||||
@@ -1,6 +1,7 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct PhosCamera {
|
||||
pub min_height: f32,
|
||||
pub max_height: f32,
|
||||
@@ -16,9 +17,9 @@ impl Default for PhosCamera {
|
||||
min_height: 10.,
|
||||
max_height: 100.,
|
||||
speed: 20.,
|
||||
zoom_speed: 20.,
|
||||
min_angle: 10.,
|
||||
max_angle: 80.,
|
||||
zoom_speed: 0.3,
|
||||
min_angle: (20. as f32).to_radians(),
|
||||
max_angle: 1.,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +27,9 @@ impl Default for PhosCamera {
|
||||
#[derive(Component, Default)]
|
||||
pub struct PhosCameraTargets {
|
||||
pub height: f32,
|
||||
pub last_height: f32,
|
||||
pub anim_time: f32,
|
||||
pub rotate_time: f32,
|
||||
}
|
||||
|
||||
#[derive(Component, Default)]
|
||||
2
game/main/src/camera_system/mod.rs
Normal file
2
game/main/src/camera_system/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod camera_plugin;
|
||||
pub mod components;
|
||||
@@ -3,13 +3,14 @@ use bevy::prelude::*;
|
||||
use bevy::render::texture::{ImageAddressMode, ImageFilterMode, ImageSamplerDescriptor};
|
||||
use bevy::window::PresentMode;
|
||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||
use phos::PhosGamePlugin;
|
||||
|
||||
mod camera_system;
|
||||
mod map_init;
|
||||
mod phos;
|
||||
mod prelude;
|
||||
mod shader_extensions;
|
||||
mod utlis;
|
||||
use phos::PhosGamePlugin;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*};
|
||||
use bevy_inspector_egui::quick::ResourceInspectorPlugin;
|
||||
use bevy_rapier3d::geometry::{Collider, TriMeshFlags};
|
||||
use camera_system::prelude::{CameraBounds, PhosCamera};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use world_generation::{
|
||||
biome_painter::*,
|
||||
@@ -15,6 +14,7 @@ use world_generation::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
camera_system::components::*,
|
||||
prelude::{ChunkAtlas, PhosChunk, PhosMap},
|
||||
shader_extensions::chunk_material::ChunkMaterial,
|
||||
utlis::render_distance_system::RenderDistanceVisibility,
|
||||
@@ -235,7 +235,11 @@ fn spawn_map(
|
||||
|
||||
commands.spawn((PbrBundle {
|
||||
transform: Transform::from_translation(heightmap.get_center()),
|
||||
mesh: meshes.add(Plane3d::default().mesh().size(heightmap.get_world_width(), heightmap.get_world_height())),
|
||||
mesh: meshes.add(
|
||||
Plane3d::default()
|
||||
.mesh()
|
||||
.size(heightmap.get_world_width(), heightmap.get_world_height()),
|
||||
),
|
||||
material: standard_materials.add(StandardMaterial {
|
||||
base_color: Color::AQUAMARINE.with_a(0.5),
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::camera_system::camera_plugin::PhosCameraPlugin;
|
||||
use crate::camera_system::components::PhosCamera;
|
||||
use crate::map_init::MapInitPlugin;
|
||||
use crate::prelude::*;
|
||||
use crate::shader_extensions::chunk_material::ChunkMaterial;
|
||||
@@ -10,8 +12,6 @@ use bevy::{
|
||||
use bevy_rapier3d::dynamics::{Ccd, RigidBody, Velocity};
|
||||
use bevy_rapier3d::geometry::Collider;
|
||||
use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin};
|
||||
use camera_system::prelude::PhosCamera;
|
||||
use camera_system::PhosCameraPlugin;
|
||||
use iyes_perf_ui::prelude::*;
|
||||
use world_generation::biome_painter::BiomePainterPlugin;
|
||||
use world_generation::tile_manager::TileAssetPlugin;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
use camera_system::prelude::PhosCamera;
|
||||
|
||||
use crate::camera_system::components::PhosCamera;
|
||||
|
||||
pub struct RenderDistancePlugin;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user