Уроки · 38
Радиус мышью
По сути это те же самые ингредиенты, что уже встречались по
отдельности: is_mouse_button_pressed/is_mouse_button_down из урока
«Отрезок мышью» — там так же фиксируется первая точка
по нажатию и тянется вторая, пока зажато, только рисуется сам
отрезок, а не вычисленное по нему расстояние; и расстояние как радиус
из урока «Расстояние» — только там радиус следовал за
курсором всё время, без клика, а здесь по отпусканию кнопки застывает
насовсем.
Нажал, тянешь, отпустил
Заголовок раздела «Нажал, тянешь, отпустил»Нажатие запоминает точку, откуда растёт кружок — она же останется его центром:
if is_mouse_button_pressed(MouseButton::Left) { drag_x = mouse_x; drag_y = mouse_y;}Пока кнопка зажата, радиус — это расстояние от той точки до курсора
прямо сейчас, тем же distance, что и в уроке «Расстояние»:
let radius = distance(drag_x, drag_y, mouse_x, mouse_y).max(5.0);.max(5.0) не даёт радиусу стать меньше 5 пикселей — если отпустить
кнопку сразу после нажатия, расстояние будет совсем крошечным или
вовсе нулевым, и кружок иначе пропал бы из виду.
Пока кнопка зажата, кружок только показывается превью — рисуется заново каждый кадр, но никуда не сохраняется:
if is_mouse_button_down(MouseButton::Left) { draw_circle(drag_x, drag_y, radius, YELLOW);}А в момент отпускания кнопки кружок сохраняется насовсем — ровно с тем радиусом, что получился к этому моменту, и со случайным цветом:
if is_mouse_button_released(MouseButton::Left) { let color = COLORS[rand::gen_range(0, COLORS.len())]; circles.push(Circle { x: drag_x, y: drag_y, radius, color });}Замени содержимое src/main.rs на это:
use macroquad::prelude::*;
// Фиксированный список цветов, из которого выбираем случайный.const COLORS: [Color; 4] = [YELLOW, RED, GREEN, BLUE];
// Один кружок: положение, радиус и цвет вместе, под понятными именами.struct Circle { x: f32, y: f32, radius: f32, color: Color,}
// Своя функция: расстояние между двумя точками, как в уроке «Расстояние».fn distance(from_x: f32, from_y: f32, to_x: f32, to_y: f32) -> f32 { let dx = to_x - from_x; let dy = to_y - from_y; (dx * dx + dy * dy).sqrt()}
#[macroquad::main("Радиус мышью")]async fn main() { // Список уже сохранённых кружков — сначала пустой. let mut circles: Vec<Circle> = Vec::new();
// Точка, где начали тянуть радиус текущего кружка. let mut drag_x = 0.0; let mut drag_y = 0.0;
loop { clear_background(BLACK);
// Координаты мыши прямо сейчас. let (mouse_x, mouse_y) = mouse_position();
// Кнопка мыши только что нажата — запоминаем точку начала. if is_mouse_button_pressed(MouseButton::Left) { drag_x = mouse_x; drag_y = mouse_y; }
// Радиус не может быть меньше 5 — иначе кружок пропадёт из виду. let radius = distance(drag_x, drag_y, mouse_x, mouse_y).max(5.0);
// Кнопка зажата — показываем, каким получится кружок. if is_mouse_button_down(MouseButton::Left) { draw_circle(drag_x, drag_y, radius, YELLOW); }
// Кнопку только что отпустили — сохраняем готовый кружок. if is_mouse_button_released(MouseButton::Left) { let color = COLORS[rand::gen_range(0, COLORS.len())]; circles.push(Circle { x: drag_x, y: drag_y, radius, color }); }
// Рисуем все уже сохранённые кружки. for circle in &circles { draw_circle(circle.x, circle.y, circle.radius, circle.color); }
next_frame().await; }}Запусти как обычно:
cargo runЗажми кнопку мыши в любой точке и, не отпуская, потяни в сторону — радиус кружка растёт вслед за мышью. Отпусти — кружок сохранится со случайным цветом. Попробуй прямо здесь:
Что здесь происходит
Заголовок раздела «Что здесь происходит»is_mouse_button_pressedставит точкуdrag_x/drag_yодин раз, в момент нажатия, — та же идея, что и у первой точки отрезка в уроке «Отрезок мышью».distance(drag_x, drag_y, mouse_x, mouse_y)— расстояние от той точки до курсора прямо сейчас, тот же приём, что и в уроке «Расстояние», только там радиус не сохранялся, а просто всё время следовал за курсором..max(5.0)не даёт радиусу стать меньше 5 пикселей — при клике без протягивания расстояние было бы совсем маленьким или нулевым.- Пока кнопка зажата, кружок только превью — рисуется каждый кадр заново, но нигде не сохраняется, поэтому и пропадает, стоит передвинуть мышь.
is_mouse_button_releasedсрабатывает один раз, в кадр отпускания — ровно тогда кружок с текущимradiusи случайным цветом попадает вcirclesи остаётся на экране уже навсегда.