camera zooming
This commit is contained in:
@@ -1,13 +1,39 @@
|
||||
use bevy::input::keyboard::KeyCode;
|
||||
use bevy::input::mouse::{MouseScrollUnit, MouseWheel};
|
||||
use bevy::prelude::*;
|
||||
use bevy::render::camera::{OrthographicProjection, Projection};
|
||||
|
||||
use crate::constants::TILE_SIZE;
|
||||
use crate::{game, tilemap};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct PanningCamera {
|
||||
pub pan_speed: f32,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct CameraMoved(pub bool);
|
||||
|
||||
pub fn camera_z_movement(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut z_index: ResMut<game::ZIndex>,
|
||||
mut camera_moved: ResMut<CameraMoved>,
|
||||
) {
|
||||
camera_moved.0 = false;
|
||||
if keyboard_input.just_pressed(KeyCode::ShiftLeft) {
|
||||
z_index.0 -= 1.0;
|
||||
z_index.0 = z_index.0.clamp(-tilemap::Z_BELOW + 1.0, tilemap::Z_ABOVE);
|
||||
camera_moved.0 = true;
|
||||
println!("z_index = {}", z_index.0);
|
||||
}
|
||||
if keyboard_input.just_pressed(KeyCode::ShiftRight) {
|
||||
z_index.0 += 1.0;
|
||||
z_index.0 = z_index.0.clamp(-tilemap::Z_BELOW + 1.0, tilemap::Z_ABOVE);
|
||||
camera_moved.0 = true;
|
||||
println!("z_index = {}", z_index.0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn camera_movement(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut query: Query<(&PanningCamera, &mut Transform), With<Camera>>,
|
||||
@@ -41,7 +67,36 @@ pub fn camera_movement(
|
||||
pub fn spawn_panning_camera(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
Camera2d,
|
||||
Projection::Orthographic(OrthographicProjection {
|
||||
scale: 1.0,
|
||||
..OrthographicProjection::default_2d()
|
||||
}),
|
||||
Transform::from_xyz(0., 0., 10. * TILE_SIZE),
|
||||
PanningCamera { pan_speed: 15.0 },
|
||||
));
|
||||
}
|
||||
|
||||
pub fn scroll_events(mut evr_scroll: EventReader<MouseWheel>, mut query: Query<&mut Projection>) {
|
||||
const ZOOM_SENSITIVITY: f32 = 0.05;
|
||||
const MIN_SCALE: f32 = 0.4;
|
||||
const MAX_SCALE: f32 = 1.5;
|
||||
|
||||
for ev in evr_scroll.read() {
|
||||
for mut projection_component in query.iter_mut() {
|
||||
let current_scale = match &*projection_component {
|
||||
Projection::Orthographic(ortho_proj) => ortho_proj.scale,
|
||||
Projection::Perspective(_) => 1.0,
|
||||
Projection::Custom(_custom_projection) => todo!(),
|
||||
};
|
||||
|
||||
let new_scale = match ev.unit {
|
||||
MouseScrollUnit::Line => current_scale + ev.y * ZOOM_SENSITIVITY,
|
||||
MouseScrollUnit::Pixel => todo!(),
|
||||
};
|
||||
*projection_component = Projection::Orthographic(OrthographicProjection {
|
||||
scale: new_scale.max(MIN_SCALE).min(MAX_SCALE),
|
||||
..OrthographicProjection::default_2d()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -17,7 +17,7 @@ impl Citizen {
|
||||
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
||||
Citizen {
|
||||
ambulatory: Ambulatory {
|
||||
walk_speed: 2.,
|
||||
walk_speed: 0.,
|
||||
run_speed: 6.,
|
||||
target: None,
|
||||
current_path: None,
|
||||
@@ -197,7 +197,8 @@ pub fn citizen_movement(
|
||||
if transform.translation.z / TILE_SIZE <= z_index.0 + 1.0 {
|
||||
*visibility = Visibility::Visible;
|
||||
let saturation =
|
||||
((z_index.0 - transform.translation.z / TILE_SIZE) / 8.0)
|
||||
((z_index.0 - (transform.translation.z / TILE_SIZE) + 1.)
|
||||
/ 8.0)
|
||||
.clamp(0.0, 1.0);
|
||||
|
||||
sprite.color =
|
||||
@@ -324,7 +325,7 @@ fn calculate_path(tilemap: &TileMap, start: IVec3, goal: IVec3) -> Vec<Vec3> {
|
||||
) {
|
||||
(1, 0, 0) | (0, 1, 0) | (0, 0, 1) => 10, // Orthogonal movement (1 axis)
|
||||
(1, 1, 0) | (1, 0, 1) | (0, 1, 1) => 14, // Diagonal movement (2 axes)
|
||||
(1, 1, 1) => 17, // Full 3D diagonal movement (3 axes)
|
||||
(1, 1, 1) => 20, // Full 3D diagonal movement (3 axes)
|
||||
_ => continue, // Invalid movement
|
||||
};
|
||||
|
||||
@@ -405,9 +406,9 @@ pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
|
||||
// Spawn a handful of citizens
|
||||
for _ in 0..100 {
|
||||
let x: f32 = rng.random_range(-8.0..8.0);
|
||||
let y: f32 = rng.random_range(-8.0..8.0);
|
||||
let mut position = Vec3::new(x.round(), y.round(), 30.0) * TILE_SIZE;
|
||||
let x: f32 = rng.random_range(-5.0..5.0);
|
||||
let y: f32 = rng.random_range(-5.0..5.0);
|
||||
let mut position = Vec3::new(x.round(), y.round(), 35.0) * TILE_SIZE;
|
||||
position.z += 0.1;
|
||||
|
||||
commands.spawn(Citizen::new(&asset_server, position));
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
pub const PIXEL_RATIO: f32 = 2.0;
|
||||
pub const PIXEL_RATIO: f32 = 1.0;
|
||||
pub const TILE_PIXELS: u32 = 16;
|
||||
pub const TILE_SIZE: f32 = TILE_PIXELS as f32 * PIXEL_RATIO;
|
||||
pub const ITILE_SIZE: i32 = TILE_SIZE as i32;
|
||||
|
||||
+6
-8
@@ -42,19 +42,17 @@ fn main() {
|
||||
)
|
||||
.add_systems(
|
||||
FixedUpdate,
|
||||
(
|
||||
camera::camera_movement,
|
||||
cursor::move_cursor,
|
||||
tiles::build_quilted_terrain_sprites,
|
||||
),
|
||||
(tiles::build_quilted_terrain_sprites, camera::scroll_events),
|
||||
)
|
||||
.init_resource::<tile::CameraMoved>()
|
||||
.init_resource::<camera::CameraMoved>()
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
tile::camera_z_movement,
|
||||
camera::camera_z_movement,
|
||||
camera::camera_movement,
|
||||
cursor::move_cursor,
|
||||
tile::update_tile_visibility
|
||||
.run_if(|camera_moved: Res<tile::CameraMoved>| camera_moved.0),
|
||||
.run_if(|camera_moved: Res<camera::CameraMoved>| camera_moved.0),
|
||||
),
|
||||
)
|
||||
.run();
|
||||
|
||||
-23
@@ -47,29 +47,6 @@ impl Default for FixtureTile {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct CameraMoved(pub bool);
|
||||
|
||||
pub fn camera_z_movement(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut z_index: ResMut<game::ZIndex>,
|
||||
mut camera_moved: ResMut<CameraMoved>,
|
||||
) {
|
||||
camera_moved.0 = false;
|
||||
if keyboard_input.just_pressed(KeyCode::ShiftLeft) {
|
||||
z_index.0 -= 1.0;
|
||||
z_index.0 = z_index.0.clamp(-tilemap::Z_BELOW + 1.0, tilemap::Z_ABOVE);
|
||||
camera_moved.0 = true;
|
||||
println!("z_index = {}", z_index.0);
|
||||
}
|
||||
if keyboard_input.just_pressed(KeyCode::ShiftRight) {
|
||||
z_index.0 += 1.0;
|
||||
z_index.0 = z_index.0.clamp(-tilemap::Z_BELOW + 1.0, tilemap::Z_ABOVE);
|
||||
camera_moved.0 = true;
|
||||
println!("z_index = {}", z_index.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default, Clone)]
|
||||
pub struct TileMap {
|
||||
pub floor_tiles: HashMap<IVec3, (u32, bool, bool, u8, [u32; 8])>, // id, opaque, walkable, astar_weight, visible_range
|
||||
|
||||
+8
-7
@@ -11,8 +11,8 @@ use noise::{NoiseFn, Perlin};
|
||||
|
||||
pub const CHUNK_SIZE: i32 = 8;
|
||||
|
||||
pub const Z_BELOW: f32 = 3.0;
|
||||
pub const Z_ABOVE: f32 = 5.0;
|
||||
pub const Z_BELOW: f32 = 20.0;
|
||||
pub const Z_ABOVE: f32 = 10.0;
|
||||
pub const Z_TOTAL: f32 = Z_ABOVE + Z_BELOW; // MAX 255 DO NOT EXCEED
|
||||
|
||||
#[derive(Resource)]
|
||||
@@ -164,6 +164,7 @@ fn generate_chunks_from_algo(
|
||||
) {
|
||||
let is_empty = events.is_empty();
|
||||
let start = Instant::now();
|
||||
let count = events.len();
|
||||
|
||||
let cave_noise = Perlin::new(0);
|
||||
for event in events.read() {
|
||||
@@ -204,9 +205,9 @@ fn generate_chunks_from_algo(
|
||||
let noise_value = cave_noise.get([
|
||||
world_x as f64 * 0.05,
|
||||
world_y as f64 * 0.05,
|
||||
z as f64 * (0.15 * -z as f64),
|
||||
z as f64 * 0.05,
|
||||
]);
|
||||
if noise_value < -0.65 {
|
||||
if noise_value < -0.85 {
|
||||
FloorTilePrefab::air(position).spawn(&mut commands);
|
||||
tilemap
|
||||
.floor_tiles
|
||||
@@ -278,13 +279,13 @@ fn generate_chunks_from_algo(
|
||||
}
|
||||
}
|
||||
if !is_empty {
|
||||
println!("Chunks loaded in {:.2?}", start.elapsed());
|
||||
println!("{} chunks loaded in {:.2?}", count, start.elapsed());
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_initial_chunks(mut event_writer: EventWriter<LoadChunkEvent>) {
|
||||
for x in -10..=10 {
|
||||
for y in -10..=10 {
|
||||
for x in -16..=16 {
|
||||
for y in -9..=9 {
|
||||
event_writer.write(LoadChunkEvent {
|
||||
chunk_position: IVec2::new(x, y),
|
||||
});
|
||||
|
||||
+19
-19
@@ -328,26 +328,26 @@ fn blit_texture_with_alpha(
|
||||
}
|
||||
|
||||
// This system handles updating quilted sprites when the world changes
|
||||
pub fn update_quilts_on_world_change(
|
||||
mut commands: Commands,
|
||||
mut quilt_cache: ResMut<QuiltCache>,
|
||||
mut cwss: ResMut<CurrentWorldSpriteState>,
|
||||
// Add any resources or queries that indicate world changes
|
||||
// For example, if you have a WorldChangeEvent:
|
||||
// mut world_changes: EventReader<WorldChangeEvent>,
|
||||
) {
|
||||
// Example: Check for world changes
|
||||
// if !world_changes.is_empty() {
|
||||
// for event in world_changes.iter() {
|
||||
// quilt_cache.dirty_indices.push(event.z_index);
|
||||
// }
|
||||
// cwss.state = WorldSpriteState::WaitingForRender;
|
||||
// }
|
||||
// pub fn update_quilts_on_world_change(
|
||||
// mut commands: Commands,
|
||||
// mut quilt_cache: ResMut<QuiltCache>,
|
||||
// mut cwss: ResMut<CurrentWorldSpriteState>,
|
||||
// Add any resources or queries that indicate world changes
|
||||
// For example, if you have a WorldChangeEvent:
|
||||
// mut world_changes: EventReader<WorldChangeEvent>,
|
||||
// ) {
|
||||
// Example: Check for world changes
|
||||
// if !world_changes.is_empty() {
|
||||
// for event in world_changes.iter() {
|
||||
// quilt_cache.dirty_indices.push(event.z_index);
|
||||
// }
|
||||
// cwss.state = WorldSpriteState::WaitingForRender;
|
||||
// }
|
||||
|
||||
// Alternatively, if you have specific systems that modify the world,
|
||||
// you could have them set cwss.state = WorldSpriteState::WaitingForRender
|
||||
// and add affected z-indices to quilt_cache.dirty_indices
|
||||
}
|
||||
// Alternatively, if you have specific systems that modify the world,
|
||||
// you could have them set cwss.state = WorldSpriteState::WaitingForRender
|
||||
// and add affected z-indices to quilt_cache.dirty_indices
|
||||
// }
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct FloorTilePrefab {
|
||||
|
||||
Reference in New Issue
Block a user