camera movement with drag + scroll zoom

This commit is contained in:
Arkitu 2025-05-23 22:18:11 +02:00
parent c6e8a3e232
commit 4a401182fb
7 changed files with 68 additions and 49 deletions

10
Cargo.lock generated
View File

@ -352,6 +352,7 @@ version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eaad7fe854258047680c51c3cacb804468553c04241912f6254c841c67c0198"
dependencies = [
"bevy_dylib",
"bevy_internal",
]
@ -583,6 +584,15 @@ dependencies = [
"sysinfo",
]
[[package]]
name = "bevy_dylib"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "381b2a0773cfe9d27256fba1e5005a14968b34f751c09397ee4e278f0fb235db"
dependencies = [
"bevy_internal",
]
[[package]]
name = "bevy_ecs"
version = "0.15.3"

View File

@ -12,6 +12,9 @@ crate-type = ["cdylib"]
path = "src/lib.rs"
name = "forestiles"
[features]
debug = ["dep:bevy_editor_pls"]
[dependencies]
bevy = { version = "0.15", default-features = false, features = [
"android-native-activity",
@ -33,6 +36,7 @@ bevy = { version = "0.15", default-features = false, features = [
"png",
"tonemapping_luts",
"bevy_pbr",
"dynamic_linking",
] }
#bevy-inspector-egui = { version = "0.28", default-features = false, features = [
# "bevy_image",
@ -44,7 +48,7 @@ log = "0.4"
rand = { version = "0.8", features = ["small_rng"] }
voronoice = "0.2"
noise = "0.9"
bevy_editor_pls = { version = "0.11", git = "https://github.com/jakobhellermann/bevy_editor_pls.git" }
bevy_editor_pls = { version = "0.11", git = "https://github.com/jakobhellermann/bevy_editor_pls.git", optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6"

View File

@ -1,4 +1,4 @@
use bevy::prelude::*;
use bevy::{prelude::*, render::camera::ScalingMode};
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
@ -11,26 +11,22 @@ impl bevy::prelude::Plugin for Plugin {
pub struct CameraMarker;
fn setup(mut cmds: Commands, window: Query<&Window>) {
let zoom = 2. / window.single().width().min(window.single().height());
cmds.spawn((
CameraMarker,
Camera3d {
..Default::default()
},
Transform::from_scale(Vec3::new(zoom, zoom, zoom))
.with_translation(Vec3::new(0., -1., 1.))
PerspectiveProjection::default(),
Transform::from_translation(Vec3::new(0., -1., 1.))
.looking_to(Vec3::new(0., 1., -1.), Vec3::Y),
));
cmds.spawn(
DirectionalLightBundle {
directional_light: DirectionalLight {
color: Color::WHITE,
illuminance: 17000.,
//shadows_enabled: true,
..Default::default()
},
transform: Transform::default().looking_to(Vec3::new(1., -1., -1.), Vec3::ZERO),
cmds.spawn((
DirectionalLight {
color: Color::WHITE,
illuminance: 17000.,
//shadows_enabled: true,
..Default::default()
}
);
},
Transform::default().looking_to(Vec3::new(1., -1., -1.), Vec3::ZERO),
));
}

View File

@ -3,7 +3,6 @@ use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*,
};
//use bevy_inspector_egui::quick::WorldInspectorPlugin;
pub mod camera;
pub mod map;
@ -16,8 +15,8 @@ pub fn main() {
.add_plugins((
DefaultPlugins,
// bevy_inspector_egui::DefaultInspectorConfigPlugin,
//bevy_editor_pls::EditorPlugin::default(), // for debug
// WorldInspectorPlugin::default(),
#[cfg(feature = "debug")]
bevy_editor_pls::EditorPlugin::default(), // for debug
camera::Plugin,
map::Plugin,
ui::Plugin,

View File

@ -31,8 +31,8 @@ impl bevy::prelude::Plugin for Plugin {
pub const HEIGHT: f32 = 2.;
pub const WIDTH: f32 = 2.;
pub const REAL_HEIGHT: f32 = 500.;
pub const REAL_WIDTH: f32 = 500.;
pub const REAL_HEIGHT: f32 = 2000.;
pub const REAL_WIDTH: f32 = 2000.;
pub const CELL_AREA: f32 = REAL_HEIGHT * REAL_WIDTH / SIZE as f32;
pub const SIZE: usize = 10000;
@ -80,23 +80,18 @@ fn setup(
for i in 0..SIZE {
let c = voronoi.cell(i);
let site = c.site_position();
let z = (
0.3 // Arbitrary value
+ ((z_noise.get([site.x, site.y])+1.)/2.) // Noise + [0; 1]
- ((site.x.powi(2)+site.y.powi(2)).sqrt()*0.5)
// Distance - [0; sqrt(2)] * 0.5
)
.clamp(0., 1.);
let z = get_altitude(&z_noise, &[site.x as f32, site.y as f32]);
info!(z);
let _m = (
(moisture_noise.get([site.x, site.y]) + 1.) / 2.
// Noise + [0; 1]
)
.clamp(0., 1.) as f32;
let k = if z <= 0.5 {
let k = if z <= 0. {
CellKind::Sea
} else if z <= 0.52 {
} else if z <= 0.04 {
CellKind::Beach
} else if z < 0.8 {
} else if z < 0.6 {
CellKind::Dirt
} else {
CellKind::Stone
@ -104,7 +99,6 @@ fn setup(
cells.push(Cell {
kind: k,
voronoi_id: i,
altitude: (z * 255.) as u8,
vertices: vec![],
});
}
@ -113,14 +107,15 @@ fn setup(
let mut indices = Vec::new();
let mut normals = Vec::new();
for (c, cd) in voronoi
.iter_cells()
.zip(cells.iter_mut())
{
for (c, cd) in voronoi.iter_cells().zip(cells.iter_mut()) {
let vs = c.iter_vertices().collect::<Vec<_>>();
let i = poss.len();
for v in vs.iter() {
poss.push(Vec3::new(v.x as f32, v.y as f32, (cd.altitude as f32)/255./4.));
poss.push(Vec3::new(
v.x as f32,
v.y as f32,
(get_altitude(&z_noise, &[v.x as f32, v.y as f32]) / 1.),
));
normals.push(Vec3::new(0., 0., 1.));
}
for v in 1..(vs.len() - 1) {
@ -198,3 +193,16 @@ fn update_map_mesh(
needs_update.0 = false;
}
}
/// Between 0 and 1
fn get_altitude(z_noise: &Fbm<Perlin>, pos: &[f32; 2]) -> f32 {
let z_noise = ((z_noise.get([pos[0] as f64, pos[1] as f64]) as f32) + 1.) / 2.; // Noise [0; 1]
(
-0.2// Arbitrary value
+ (z_noise.exp() / 1f32.exp())
// Noise + [0; 1]
// - ((pos[0].powi(2)+pos[1].powi(2)).sqrt()*0.3)
// Distance - [0; sqrt(2)] * 0.5
)
// .clamp(-1., 1.)
}

View File

@ -36,7 +36,6 @@ impl CellKind {
pub struct Cell {
pub kind: CellKind,
pub voronoi_id: usize,
pub altitude: u8,
pub vertices: Vec<usize>,
}
impl Cell {

View File

@ -9,8 +9,8 @@ use bevy::{
};
use mevy::*;
use crate::map::{AnimalKind, CellKind};
use crate::camera::CameraMarker;
use crate::map::{AnimalKind, CellKind};
// #77767b
const TABBAR_COLOR: Color = Color::srgb(119. / 255., 118. / 255., 123. / 255.);
@ -65,7 +65,7 @@ fn setup(mut world: Commands, asset_server: Res<AssetServer>) {
.observe(|
trigger: Trigger<Pointer<Drag>>,
mut ptrs: Query<&mut PointersDragging>,
mut cam: Query<&mut Transform, With<CameraMarker>>,
mut cam: Query<(&mut Transform, &PerspectiveProjection), With<CameraMarker>>,
| {
if trigger.button == PointerButton::Primary {
let mut ptrs = ptrs.single_mut();
@ -81,12 +81,12 @@ fn setup(mut world: Commands, asset_server: Res<AssetServer>) {
let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm());
// move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y;
cam.0.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.1.fov*0.001;
cam.0.translation.y += (new_midpoint.y - old_midpoint.y)*cam.1.fov*0.001;
if ptrs.0.len() > 1 {
cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
}
// if ptrs.0.len() > 1 {
// cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
// }
}
}
);
@ -199,9 +199,12 @@ fn zoom_with_scroll(
let window = window.single();
let mut cam = cam.single_mut();
for ev in ev_scroll.read() {
let scale = (cam.scale.x - (ev.y * 0.1 / window.width().min(window.height())))
.clamp(0.0001, 2. / window.width().min(window.height()));
cam.scale = Vec3::new(scale, scale, scale);
dbg!(ev.y);
let forward = cam.forward();
cam.translation += forward * (ev.y * 0.1);
// cam.fov = cam.fov + (ev.y * 0.1);
// let scale = (cam.scale.x - (ev.y * 0.1 / window.width().min(window.height())))
// .clamp(0.0001, 2. / window.width().min(window.height()));
}
}
}