Перейти к содержимому

Дополнительно · 1

Относительные координаты

В уроке “Доля от 0 до 1” мы узнали, что число от 0 до 1 — это доля. Если её умножить на любое другое число, получится результат где-то между 0 и этим числом:

let n = 10.0;
let p = 0.5;
let result = n * p; // result = 5.0 — где-то между 0 и n

0.5 от 10 — это 5, а 0.5 от 1000 — это 500. Само число (назовём его N) может быть каким угодно — доля всегда просто “нарезает” его на нужную часть.

Ниже — число N (какое хочешь) и доля P от 0 до 1. Верхняя полоска — это диапазон от 0 до 1. Нижняя — диапазон от 0 до N, растянутый на всю ширину, в том же масштабе. Красная линия показывает, куда попадает доля P и какому числу это соответствует внутри N:

0.52.50105

Меняй P — красная линия скользит по обеим полоскам одновременно: верхняя (0–1) и нижняя (0–N) используют один и тот же масштаб, просто нижняя длиннее ровно в N раз.

Меняй и N — при большом N верхняя полоска становится совсем короткой. Это не случайно: нижняя полоска всегда растянута на всю ширину экрана — ей больше некуда расти. А раз масштаб общий, то, чтобы уместить бо́льший N на той же ширине, приходится ужимать верхнюю полоску, а не пытаться бесконечно растягивать нижнюю.

Доля особенно полезна, когда нужно задать позицию внутри чего-то, чей размер заранее неизвестен или может поменяться — например, круга, экрана или окна. Координаты, которые заданы просто числом пикселей, называются абсолютными — они не подстраиваются под размер. А координаты, заданные долей от 0 до 1, называются относительными — они всегда остаются “на своём месте”, какой бы ни был размер.

Внутри большого круга нарисован маленький жёлтый кружок, смещённый от центра на фиксированное число пикселей:

Смещение жёлтого кружка от центра большого круга задано просто числом пикселей — это и есть абсолютные координаты. Сколько бы ты ни менял радиус R большого круга, жёлтый кружок остаётся на том же самом месте — а если радиус станет меньше смещения, кружок вообще окажется снаружи:

src/main.rs
use macroquad::prelude::*;
#[macroquad::main("Абсолютные координаты")]
async fn main() {
// Центр экрана — считаем один раз, до loop.
let center_x = screen_width() / 2.0;
let center_y = screen_height() / 2.0;
loop {
clear_background(BLACK);
// Большой круг — по центру, радиусом R.
draw_circle(center_x, center_y, 400.0, DARKBLUE);
// Жёлтый кружок — смещён от центра на фиксированное число пикселей.
draw_circle(center_x + 200.0, center_y, 40.0, YELLOW);
next_frame().await;
}
}

А вот то же самое, но смещение задано не числом пикселей, а долей от радиуса — radius, умноженный на percent:

Теперь смещение жёлтого кружка — это радиус R, умноженный на долю P от 0 до 1. Меняй R и P — кружок всегда остаётся где-то между центром и краем большого круга, каким бы ни был радиус:

src/main.rs
use macroquad::prelude::*;
#[macroquad::main("Относительные координаты")]
async fn main() {
// Центр экрана — считаем один раз, до loop.
let center_x = screen_width() / 2.0;
let center_y = screen_height() / 2.0;
loop {
clear_background(BLACK);
// Большой круг — по центру, радиусом R.
draw_circle(center_x, center_y, 400.0, DARKBLUE);
// Жёлтый кружок — смещён на долю P от радиуса R.
draw_circle(center_x + 400.0 * 0.5, center_y, 40.0, YELLOW);
next_frame().await;
}
}
  • В первом примере смещение (200.0) — обычное число пикселей. Оно не знает про радиус круга и не меняется вместе с ним.
  • Во втором примере смещение — это radius * percent. Раз оно зависит от radius, оно само подстраивается, когда радиус меняется.
  • percent (доля от 0 до 1) — это то же самое число P из демки с масштабом выше: оно выбирает позицию “внутри” радиуса, не зная заранее, каким конкретно будет сам радиус.