Skip to content

Commit

Permalink
feat(camera): add mouse-driven panning
Browse files Browse the repository at this point in the history
Enable panning of the camera based on
the cursor position relative to the viewport.
  • Loading branch information
ShenMian committed Jul 20, 2024
1 parent 9d647ff commit 4e230a8
Showing 1 changed file with 40 additions and 11 deletions.
51 changes: 40 additions & 11 deletions src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,59 @@ fn spawn(mut commands: Commands) {

pub fn update(
keys: Res<ButtonInput<KeyCode>>,
mut query: Query<(Ref<OrthographicProjection>, &mut Transform), With<Camera2d>>,
mut query: Query<(&OrthographicProjection, &mut Transform), With<Camera2d>>,
time: Res<Time>,
tilemaps: Res<Assets<Map>>,
tilemap_query: Query<&Handle<Map>>,
window_query: Query<&Window>,
) {
let Ok((projection, mut transform)) = query.get_single_mut() else {
return;
};

let min_speed = 250.;
let max_speed = 500.;

let x = keys.any_pressed([KeyCode::ArrowRight, KeyCode::KeyD]) as i8
- keys.any_pressed([KeyCode::ArrowLeft, KeyCode::KeyA]) as i8;
let y = keys.any_pressed([KeyCode::ArrowUp, KeyCode::KeyW]) as i8
- keys.any_pressed([KeyCode::ArrowDown, KeyCode::KeyS]) as i8;
let dir = Vec2::new(x as f32, y as f32).normalize_or_zero();

let Ok((projection, mut transform)) = query.get_single_mut() else {
if dir != Vec2::ZERO {
let speed = if keys.any_pressed([KeyCode::ShiftLeft, KeyCode::ShiftRight]) {
max_speed
} else {
min_speed
};

transform.translation += dir.extend(0.) * time.delta_seconds() * speed;
}

let Ok(window) = window_query.get_single() else {
return;
};

if dir == Vec2::ZERO && !projection.is_changed() {
return;
if let Some(cursor_position) = window.cursor_position() {
fn map_range(from: (f32, f32), to: (f32, f32), value: f32) -> f32 {
to.0 + (value - from.0) * (to.1 - to.0) / (from.1 - from.0)
}

let cursor_position = Vec2::new(cursor_position.x, cursor_position.y);
let half_viewport_size = window.resolution.size() / 2.;
let center_to_cursor = cursor_position - half_viewport_size;
let normalized_length = center_to_cursor / half_viewport_size;

if normalized_length.x.abs() >= 0.8 {
transform.translation.x += time.delta_seconds()
* map_range((0.8, 1.), (min_speed, max_speed), normalized_length.x.abs())
.copysign(normalized_length.x);
}
if normalized_length.y.abs() >= 0.8 {
transform.translation.y -= time.delta_seconds()
* map_range((0.8, 1.), (min_speed, max_speed), normalized_length.y.abs())
.copysign(normalized_length.y);
}
}

let Ok(tilemap_handle) = tilemap_query.get_single() else {
Expand All @@ -45,12 +81,6 @@ pub fn update(
return;
};

let speed = if keys.any_pressed([KeyCode::ShiftLeft, KeyCode::ShiftRight]) {
500.
} else {
250.
};

let pan_area = tilemap.size_vec2() * crate::tilemap::SCALE * crate::tilemap::TILE_SIZE
- projection.area.size();

Expand All @@ -61,7 +91,6 @@ pub fn update(
let min = pan_area / -2.;
let max = pan_area / 2.;

transform.translation += dir.extend(0.) * time.delta_seconds() * speed;
transform.translation.x = transform.translation.x.clamp(min.x, max.x);
transform.translation.y = transform.translation.y.clamp(min.y, max.y);
}

0 comments on commit 4e230a8

Please sign in to comment.