rts camera

center camera
spawn basic water
fix generator config
set camera bounds
This commit is contained in:
2024-05-02 22:11:40 -04:00
parent b2622f2126
commit ed94f77323
5 changed files with 127 additions and 36 deletions

View File

@@ -19,6 +19,7 @@ pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32) -> Map {
chunks, chunks,
height: cfg.size.y as usize, height: cfg.size.y as usize,
width: cfg.size.x as usize, width: cfg.size.x as usize,
sea_level: cfg.sea_level as f32,
}; };
} }
@@ -40,12 +41,8 @@ pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed:
(x as f64 + chunk_x * Chunk::SIZE as f64) / &cfg.noise_scale, (x as f64 + chunk_x * Chunk::SIZE as f64) / &cfg.noise_scale,
(z as f64 + chunk_z * Chunk::SIZE as f64) / &cfg.noise_scale, (z as f64 + chunk_z * Chunk::SIZE as f64) / &cfg.noise_scale,
]) as f32; ]) as f32;
temp[x + z * Chunk::SIZE] = sample_tempurature( temp[x + z * Chunk::SIZE] =
z as f32 + chunk_z as f32 * Chunk::SIZE as f32, sample_tempurature(z as f32 + chunk_z as f32 * Chunk::SIZE as f32, sample, &cfg, 100.);
sample,
&cfg,
100.,
);
} }
} }
return Chunk { return Chunk {
@@ -95,10 +92,7 @@ fn sample_point(x: f64, z: f64, cfg: &GenerationConfig, noise: &impl NoiseFn<f64
let d1 = p.x.min(p.y); let d1 = p.x.min(p.y);
let od = outer - p; let od = outer - p;
let d2 = od.x.min(od.y); let d2 = od.x.min(od.y);
let d = d1 let d = d1.min(d2).min(cfg.border_size).remap(0., cfg.border_size, 0., 1.);
.min(d2)
.min(cfg.border_size)
.remap(0., cfg.border_size, 0., 1.);
return (elevation as f32) * d; return (elevation as f32) * d;
} }

View File

@@ -8,7 +8,7 @@ pub mod tile_manager;
pub mod tile_mapper; pub mod tile_mapper;
pub mod prelude { pub mod prelude {
use crate::hex_utils::{HexCoord, INNER_RADIUS, OUTER_RADIUS}; use crate::hex_utils::{tile_to_world_distance, HexCoord, INNER_RADIUS, OUTER_RADIUS};
use bevy::math::{IVec2, UVec2, Vec2, Vec3}; use bevy::math::{IVec2, UVec2, Vec2, Vec3};
use bevy::prelude::Resource; use bevy::prelude::Resource;
use bevy::prelude::*; use bevy::prelude::*;
@@ -84,6 +84,7 @@ pub mod prelude {
pub chunks: Vec<Chunk>, pub chunks: Vec<Chunk>,
pub height: usize, pub height: usize,
pub width: usize, pub width: usize,
pub sea_level: f32,
} }
impl Map { impl Map {
@@ -105,7 +106,7 @@ pub mod prelude {
return results; return results;
} }
pub fn get_height(&self, pos: &HexCoord) -> f32 { pub fn sample_height(&self, pos: &HexCoord) -> f32 {
let chunk = &self.chunks[pos.to_chunk_index(self.width)]; let chunk = &self.chunks[pos.to_chunk_index(self.width)];
return chunk.heights[pos.to_chunk_local_index()]; return chunk.heights[pos.to_chunk_local_index()];
} }
@@ -119,6 +120,23 @@ pub mod prelude {
let chunk = &self.chunks[pos.to_chunk_index(self.width)]; let chunk = &self.chunks[pos.to_chunk_index(self.width)];
return chunk.temperature[pos.to_chunk_local_index()]; return chunk.temperature[pos.to_chunk_local_index()];
} }
pub fn get_center(&self) -> Vec3 {
let w = self.width * Chunk::SIZE;
let h = self.height * Chunk::SIZE;
return Vec3::new(
tile_to_world_distance(w as i32 / 2),
self.sea_level,
tile_to_world_distance(h as i32 / 2),
);
}
pub fn get_world_width(&self) -> f32 {
return tile_to_world_distance((self.width * Chunk::SIZE) as i32);
}
pub fn get_world_height(&self) -> f32 {
return tile_to_world_distance((self.height * Chunk::SIZE) as i32);
}
} }
pub const ATTRIBUTE_PACKED_VERTEX_DATA: MeshVertexAttribute = pub const ATTRIBUTE_PACKED_VERTEX_DATA: MeshVertexAttribute =
MeshVertexAttribute::new("PackedVertexData", 988540817, VertexFormat::Uint32); MeshVertexAttribute::new("PackedVertexData", 988540817, VertexFormat::Uint32);

View File

@@ -1,9 +1,10 @@
use crate::prelude::PhosCamera; use crate::prelude::PhosCamera;
use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin}; use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin};
use bevy::input::mouse::MouseMotion; use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
use bevy::pbr::ScreenSpaceAmbientOcclusionBundle; use bevy::pbr::ScreenSpaceAmbientOcclusionBundle;
use bevy::prelude::*; use bevy::prelude::*;
use bevy::window::CursorGrabMode; use bevy::window::CursorGrabMode;
use prelude::{CameraBounds, PhosCameraTargets};
pub mod prelude; pub mod prelude;
@@ -11,8 +12,12 @@ pub struct PhosCameraPlugin;
impl Plugin for PhosCameraPlugin { impl Plugin for PhosCameraPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Startup, setup) app.add_systems(PreStartup, setup);
.add_systems(Update, (grab_mouse, (update_camera, update_camera_mouse).chain()));
app.add_systems(Update, (rts_camera_system, apply_camera_height).chain());
app.add_systems(PostUpdate, limit_camera_bounds);
//Free Cam
//app.add_systems(Update, (grab_mouse, (update_camera, update_camera_mouse).chain()));
app.add_plugins(TemporalAntiAliasPlugin); app.add_plugins(TemporalAntiAliasPlugin);
} }
@@ -22,13 +27,16 @@ fn setup(mut commands: Commands, mut msaa: ResMut<Msaa>) {
commands commands
.spawn(( .spawn((
Camera3dBundle { Camera3dBundle {
transform: Transform::from_xyz(0., 30., 0.).looking_at(Vec3::new(1000., 0., 1000.), Vec3::Y), transform: Transform::from_xyz(0., 30., 0.)
.with_rotation(Quat::from_axis_angle(Vec3::Y, (-90 as f32).to_radians())),
..default() ..default()
}, },
PhosCamera { PhosCamera {
speed: 100., speed: 100.,
zoom_speed: 20.,
..default() ..default()
}, },
PhosCameraTargets::default(),
)) ))
.insert(ScreenSpaceAmbientOcclusionBundle::default()) .insert(ScreenSpaceAmbientOcclusionBundle::default())
.insert(TemporalAntiAliasBundle::default()); .insert(TemporalAntiAliasBundle::default());
@@ -119,17 +127,18 @@ fn grab_mouse(mut windows: Query<&mut Window>, mouse: Res<ButtonInput<MouseButto
} }
fn rts_camera_system( fn rts_camera_system(
mut cam_query: Query<(&mut Transform, &PhosCamera)>, mut cam_query: Query<(&mut Transform, &PhosCamera, &mut PhosCameraTargets)>,
key: Res<ButtonInput<KeyCode>>, key: Res<ButtonInput<KeyCode>>,
time: Res<Time>, time: Res<Time>,
mut wheel: EventReader<MouseWheel>,
) { ) {
let (mut cam, cam_cfg) = cam_query.single_mut(); let (mut cam, cam_cfg, mut cam_targets) = cam_query.single_mut();
let mut cam_move = Vec3::ZERO; let mut cam_move = Vec3::ZERO;
if key.pressed(KeyCode::KeyA) { if key.pressed(KeyCode::KeyA) {
cam_move.x = -1.;
} else if key.pressed(KeyCode::KeyD) {
cam_move.x = 1.; cam_move.x = 1.;
} else if key.pressed(KeyCode::KeyD) {
cam_move.x = -1.;
} }
if key.pressed(KeyCode::KeyW) { if key.pressed(KeyCode::KeyW) {
@@ -138,5 +147,30 @@ fn rts_camera_system(
cam_move.z = -1.; cam_move.z = -1.;
} }
cam.translation += cam_move.normalize() * cam_cfg.speed * time.delta_seconds(); 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();
for e in wheel.read() {
match e.unit {
MouseScrollUnit::Line => cam_targets.height -= e.y * 20.,
MouseScrollUnit::Pixel => cam_targets.height -= e.y,
}
}
cam_targets.height = cam_targets.height.clamp(cam_cfg.min_height, cam_cfg.max_height);
cam.translation += cam_move;
}
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)>) {
} }

View File

@@ -1,14 +1,44 @@
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Component, Default)] #[derive(Component)]
pub struct PhosCamera { pub struct PhosCamera {
pub min_height: f32, pub min_height: f32,
pub max_height: f32, pub max_height: f32,
pub speed: f32, pub speed: f32,
pub zoom_speed: f32, pub zoom_speed: f32,
pub min_angle: f32,
pub max_angle: f32,
} }
impl Default for PhosCamera {
fn default() -> Self {
Self {
min_height: 10.,
max_height: 100.,
speed: 20.,
zoom_speed: 20.,
min_angle: 10.,
max_angle: 80.,
}
}
}
#[derive(Component, Default)]
pub struct PhosCameraTargets {
pub height: f32,
}
#[derive(Component, Default)]
pub struct CameraBounds { pub struct CameraBounds {
pub min: Vec2, pub min: Vec2,
pub max: Vec2, pub max: Vec2,
} }
impl CameraBounds {
pub fn from_size(size: UVec2) -> Self {
return Self {
min: Vec2::ZERO,
max: size.as_vec2(),
};
}
}

View File

@@ -1,7 +1,7 @@
use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*}; use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*};
use bevy_inspector_egui::quick::ResourceInspectorPlugin; use bevy_inspector_egui::quick::ResourceInspectorPlugin;
use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; use bevy_rapier3d::geometry::{Collider, TriMeshFlags};
use camera_system::prelude::PhosCamera; use camera_system::prelude::{CameraBounds, PhosCamera};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use world_generation::{ use world_generation::{
biome_painter::*, biome_painter::*,
@@ -29,7 +29,8 @@ impl Plugin for MapInitPlugin {
ResourceInspectorPlugin::<GenerationConfig>::default(), ResourceInspectorPlugin::<GenerationConfig>::default(),
)); ));
app.add_systems(Startup, (load_textures, load_tiles, create_map)); app.add_systems(Startup, (load_textures, load_tiles));
app.add_systems(PostStartup, create_map);
app.add_systems(Update, finalize_texture); app.add_systems(Update, finalize_texture);
app.add_systems(PostUpdate, (despawn_map, spawn_map).chain()); app.add_systems(PostUpdate, (despawn_map, spawn_map).chain());
@@ -87,13 +88,13 @@ fn finalize_texture(
map.regenerate = true; map.regenerate = true;
} }
fn create_map(mut commands: Commands, mut cam: Query<&mut Transform, With<PhosCamera>>) { fn create_map(mut commands: Commands, mut cam: Query<(&mut Transform, Entity), With<PhosCamera>>) {
let config = GenerationConfig { let config = GenerationConfig {
layers: vec![ layers: vec![
GeneratorLayer { GeneratorLayer {
base_roughness: 2.14, base_roughness: 2.14,
roughness: 0.87, roughness: 0.87,
strength: 2.93, strength: 8.3,
min_value: -0.2, min_value: -0.2,
persistence: 0.77, persistence: 0.77,
is_rigid: false, is_rigid: false,
@@ -117,7 +118,7 @@ fn create_map(mut commands: Commands, mut cam: Query<&mut Transform, With<PhosCa
GeneratorLayer { GeneratorLayer {
base_roughness: 2.6, base_roughness: 2.6,
roughness: 4., roughness: 4.,
strength: 4.3, strength: 3.1,
min_value: 0., min_value: 0.,
persistence: 1.57, persistence: 1.57,
is_rigid: true, is_rigid: true,
@@ -148,7 +149,7 @@ fn create_map(mut commands: Commands, mut cam: Query<&mut Transform, With<PhosCa
weight: 1., weight: 1.,
weight_multi: 4.57, weight_multi: 4.57,
layers: 3, layers: 3,
first_layer_mask: true, first_layer_mask: false,
}, },
], ],
noise_scale: 450., noise_scale: 450.,
@@ -161,12 +162,14 @@ fn create_map(mut commands: Commands, mut cam: Query<&mut Transform, With<PhosCa
commands.insert_resource(heightmap); commands.insert_resource(heightmap);
// let mut cam_t = cam.single_mut(); let (mut cam_t, cam_entity) = cam.single_mut();
// cam_t.translation = Vec3::new( cam_t.translation = Vec3::new(
// tile_to_world_distance(config.size.x as i32 / 2), tile_to_world_distance((config.size.x as i32 * Chunk::SIZE as i32) / 2),
// cam_t.translation.y, cam_t.translation.y,
// tile_to_world_distance(config.size.y as i32 / 2), tile_to_world_distance((config.size.y as i32 * Chunk::SIZE as i32) / 2),
// ); );
commands.entity(cam_entity).insert(CameraBounds::from_size(config.size));
commands.insert_resource(config); commands.insert_resource(config);
} }
@@ -174,7 +177,8 @@ fn create_map(mut commands: Commands, mut cam: Query<&mut Transform, With<PhosCa
fn spawn_map( fn spawn_map(
heightmap: Res<Map>, heightmap: Res<Map>,
mut commands: Commands, mut commands: Commands,
mut materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, ChunkMaterial>>>, mut chunk_materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, ChunkMaterial>>>,
mut standard_materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
atlas: Res<ChunkAtlas>, atlas: Res<ChunkAtlas>,
mut map: ResMut<PhosMap>, mut map: ResMut<PhosMap>,
@@ -188,7 +192,7 @@ fn spawn_map(
} }
let b_painter = biome_painters.get(painter.0.clone()); let b_painter = biome_painters.get(painter.0.clone());
map.regenerate = false; map.regenerate = false;
let chunk_material = materials.add(ExtendedMaterial { let chunk_material = chunk_materials.add(ExtendedMaterial {
base: StandardMaterial::default(), base: StandardMaterial::default(),
extension: ChunkMaterial { extension: ChunkMaterial {
array_texture: atlas.handle.clone(), array_texture: atlas.handle.clone(),
@@ -228,6 +232,17 @@ fn spawn_map(
Collider::trimesh_with_flags(col_verts, col_indicies, TriMeshFlags::MERGE_DUPLICATE_VERTICES), Collider::trimesh_with_flags(col_verts, col_indicies, TriMeshFlags::MERGE_DUPLICATE_VERTICES),
)); ));
} }
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())),
material: standard_materials.add(StandardMaterial {
base_color: Color::AQUAMARINE.with_a(0.5),
alpha_mode: AlphaMode::Blend,
..default()
}),
..default()
},));
} }
fn despawn_map( fn despawn_map(