fix: adjust pet size to screen resolution

This commit is contained in:
2026-11-01 14:32:45 +03:00
parent 5afddf6969
commit 90704cee48
2 changed files with 111 additions and 20 deletions
+26 -19
View File
@@ -6,6 +6,7 @@ mod climbing;
pub use climbing::ClimbState;
pub const SPRITE_SCALE: f64 = 3.0;
const REFERENCE_SCREEN_HEIGHT: f64 = 1080.0;
const WALK_SPEED: f64 = 2.0 / 0.03;
const GRAVITY: f64 = 900.0;
const SNAP_DISTANCE: f64 = 30.0;
@@ -350,6 +351,7 @@ pub struct World {
pub quit_requested: bool,
pub sounds: Vec<&'static str>,
pub quitting: Option<f64>,
screen_scale: f64,
rng: StdRng,
next_id: i32,
menu_actor: Option<i32>,
@@ -378,6 +380,7 @@ impl World {
quit_requested: false,
sounds: Vec::with_capacity(8),
quitting: None,
screen_scale: 1.0,
rng,
next_id: 2,
menu_actor: None,
@@ -389,6 +392,7 @@ impl World {
pub fn update_desktop(&mut self, snapshot: DesktopSnapshot) {
let first = self.pets.is_empty();
self.screen_scale = (snapshot.screen.height / REFERENCE_SCREEN_HEIGHT).clamp(0.5, 2.0);
self.bounds = snapshot
.work_area
.intersection(snapshot.screen)
@@ -422,7 +426,7 @@ impl World {
self.pets.push(pet);
}
for pet in &mut self.pets {
fit_scale(pet, self.bounds);
fit_scale(pet, self.bounds, self.screen_scale, self.sitting);
reconcile_pet(
pet,
self.sitting,
@@ -524,23 +528,11 @@ impl World {
return;
}
let previous_scale = pet.scale;
let (previous_width, _) = pet.size(self.sitting, None);
let previous_anchor = pet.attachment_height(self.sitting);
pet.requested_scale = requested_scale;
fit_scale(pet, self.bounds);
fit_scale(pet, self.bounds, self.screen_scale, self.sitting);
if pet.scale == previous_scale {
return;
}
let ratio = pet.scale / previous_scale;
if pet.dragging {
let (offset_x, offset_y) = pet.drag_offset;
pet.drag_offset = (offset_x * ratio, offset_y * ratio);
pet.x += offset_x - pet.drag_offset.0;
pet.y += offset_y - pet.drag_offset.1;
} else {
pet.x += previous_width * (1.0 - ratio) / 2.0;
pet.y += previous_anchor * (1.0 - ratio);
}
reconcile_pet(
pet,
self.sitting,
@@ -600,7 +592,7 @@ impl World {
self.bounds.y + self.rng.random_range(0.1..0.7) * self.bounds.height,
);
self.next_id += 1;
fit_scale(&mut pet, self.bounds);
fit_scale(&mut pet, self.bounds, self.screen_scale, false);
let (width, height) = pet.size(false, None);
(pet.x, pet.y) = constrain_position(self.bounds, &self.panels, pet.x, pet.y, width, height);
self.pets.push(pet);
@@ -655,7 +647,7 @@ impl World {
velocity_y: 0.0,
});
self.next_id += 1;
fit_scale(main, self.bounds);
fit_scale(main, self.bounds, self.screen_scale, self.sitting);
reconcile_pet(
main,
self.sitting,
@@ -955,13 +947,28 @@ impl World {
}
}
fn fit_scale(pet: &mut PetState, bounds: Rectangle) {
fn fit_scale(pet: &mut PetState, bounds: Rectangle, screen_scale: f64, sitting: bool) {
let previous_scale = pet.scale;
let (previous_width, _) = pet.size(sitting, None);
let previous_anchor = pet.attachment_height(sitting);
let image = pet.image(false, None);
pet.scale = pet
.requested_scale
pet.scale = (screen_scale * pet.requested_scale)
.min(bounds.width / image.width)
.min(bounds.height / image.height)
.max(0.01);
if pet.scale == previous_scale {
return;
}
let ratio = pet.scale / previous_scale;
if pet.dragging {
let (offset_x, offset_y) = pet.drag_offset;
pet.drag_offset = (offset_x * ratio, offset_y * ratio);
pet.x += offset_x - pet.drag_offset.0;
pet.y += offset_y - pet.drag_offset.1;
} else {
pet.x += previous_width * (1.0 - ratio) / 2.0;
pet.y += previous_anchor * (1.0 - ratio);
}
}
pub fn visible_surfaces(windows: &[WindowRecord], bounds: Rectangle) -> Vec<Surface> {
+85 -1
View File
@@ -11,7 +11,7 @@ fn rectangle(x: f64, y: f64, width: f64, height: f64) -> Rectangle {
fn snapshot(windows: Vec<WindowRecord>) -> DesktopSnapshot {
DesktopSnapshot {
screen: rectangle(0.0, 0.0, 1280.0, 800.0),
screen: rectangle(0.0, 0.0, 1280.0, 1080.0),
work_area: rectangle(40.0, 24.0, 1240.0, 728.0),
windows,
panels: vec![rectangle(0.0, 752.0, 1280.0, 48.0)],
@@ -470,6 +470,90 @@ fn bicycle_doubles_vertical_climbing_speed() {
}
}
#[test]
fn initial_size_tracks_screen_height_and_not_panel_size() {
for (screen_width, screen_height, expected_size) in [
(1280.0, 720.0, (48.0, 64.0)),
(1920.0, 1080.0, (72.0, 96.0)),
(3840.0, 2160.0, (144.0, 192.0)),
] {
let mut desktop = snapshot(Vec::new());
desktop.screen = rectangle(0.0, 0.0, screen_width, screen_height);
desktop.work_area = desktop.screen;
desktop.panels.clear();
let mut world = World::with_rng(StdRng::seed_from_u64(9));
world.update_desktop(desktop);
assert_eq!(world.pets[0].size(false, None), expected_size);
let mut desktop = snapshot(Vec::new());
desktop.screen = rectangle(0.0, 0.0, screen_width, screen_height);
desktop.work_area = rectangle(0.0, 0.0, screen_width, screen_height - 48.0);
desktop.panels.clear();
world.update_desktop(desktop);
assert_eq!(world.pets[0].size(false, None), expected_size);
}
}
#[test]
fn wheel_limits_follow_the_screen_relative_default() {
let mut desktop = snapshot(Vec::new());
desktop.screen = rectangle(0.0, 0.0, 1280.0, 720.0);
desktop.work_area = desktop.screen;
desktop.panels.clear();
let mut world = World::with_rng(StdRng::seed_from_u64(9));
world.update_desktop(desktop);
for _ in 0..6 {
world.resize_pet(1, -1.0);
}
assert_eq!(world.pets[0].size(false, None), (24.0, 32.0));
for _ in 0..18 {
world.resize_pet(1, 1.0);
}
assert_eq!(world.pets[0].size(false, None), (96.0, 128.0));
}
#[test]
fn screen_resize_preserves_user_scale_and_drag_grip() {
let mut world = world();
world.pets[0].x = 300.0;
world.pets[0].y = 350.0;
let cursor = (318.0, 380.0);
world.begin_drag(1, cursor.0, cursor.1);
world.resize_pet(1, 6.0);
assert_eq!(world.pets[0].size(false, None), (108.0, 144.0));
let mut desktop = snapshot(Vec::new());
desktop.screen.height = 720.0;
world.update_desktop(desktop);
let pet = &world.pets[0];
assert_eq!(pet.size(false, None), (72.0, 96.0));
assert_eq!(
(pet.x + pet.drag_offset.0, pet.y + pet.drag_offset.1),
cursor
);
world.update_desktop(snapshot(Vec::new()));
let pet = &world.pets[0];
assert_eq!(pet.size(false, None), (108.0, 144.0));
assert_eq!(
(pet.x + pet.drag_offset.0, pet.y + pet.drag_offset.1),
cursor
);
}
#[test]
fn screen_resize_keeps_the_pet_on_its_titlebar() {
let mut world = world();
attach_to_target(&mut world);
let mut desktop = snapshot(vec![window("target", 100.0, 320.0, 800.0, 1)]);
desktop.screen.height = 720.0;
world.update_desktop(desktop);
let pet = &world.pets[0];
assert_eq!(pet.size(false, None), (48.0, 64.0));
assert_eq!(pet.y + pet.attachment_height(false), 320.0);
assert!(matches!(&pet.support, Some(Support::Window { id, .. }) if id == "target"));
}
#[test]
fn resize_limits_survive_desktop_and_effect_changes() {
let mut world = world();