Уроки · 43
Прямоугольные кнопки
В уроке «Круглые кнопки» попадание мыши в круг проверялось
одной формулой — расстояние меньше радиуса. С прямоугольником так не
выйдет: у него нет одного числа вроде радиуса, которое отвечало бы
сразу за форму целиком. Нужно проверить x и y мыши отдельно.
Свой тип данных для прямоугольников
Заголовок раздела «Свой тип данных для прямоугольников»Раньше struct Circle описывала круг. Здесь нужен новый тип —
специально для прямоугольников, со своими полями:
struct Rectangle { x: f32, y: f32, width: f32, height: f32, color: Color,}x, y — левый верхний угол, width и height — размер, всё как в
уроке «Прямоугольник», только теперь это не отдельные
переменные, а поля одной структуры — так же, как раньше x, y и
radius были полями Circle.
Проверка по частям
Заголовок раздела «Проверка по частям»Мышь внутри прямоугольника, если одновременно верны четыре вещи: её
x не левее левого края, её x не правее правого края, её y не
выше верхнего края, её y не ниже нижнего края. Для этого нужны два
новых знака сравнения, >= и <= — то же самое “больше” и “меньше”
из урока «Радиус обнаружения», только включающее ещё и
равенство: “больше или равно” и “меньше или равно”. Мышь на самом краю
прямоугольника должна по-прежнему считаться внутри, а не снаружи —
поэтому именно >=/<=, а не строгие >/<. Каждую из четырёх
проверок можно сохранить в свою переменную:
let after_left = mouse_x >= button.x;let before_right = mouse_x <= button.x + button.width;let after_top = mouse_y >= button.y;let before_bottom = mouse_y <= button.y + button.height;
let inside = after_left && before_right && after_top && before_bottom;&& здесь связывает не два условия, а сразу четыре — работает
ровно так же, как в уроке «Круглые кнопки», просто цепочка
подлиннее: результат — true, только если верны все четыре, а
не только первые два.
Раз каждая переменная используется всего один раз, промежуточные имена можно и не заводить — то же самое условие целиком:
let inside = mouse_x >= button.x && mouse_x <= button.x + button.width && mouse_y >= button.y && mouse_y <= button.y + button.height;Логика та же самая, просто без лишних имён по дороге — именно так это и будет в коде ниже.
Это работает только для прямоугольников, стороны которых идут строго по горизонтали и вертикали экрана, не повёрнутых ни на какой угол. Стоит прямоугольник повернуть — проверка перестанет работать, но с поворотами мы пока не знакомы, это тема для другого урока.
Замени содержимое src/main.rs на это:
use macroquad::prelude::*;
// Один прямоугольник-кнопка: положение, размер и обычный цвет.struct Rectangle { x: f32, y: f32, width: f32, height: f32, color: Color,}
#[macroquad::main("Прямоугольные кнопки")]async fn main() { loop { clear_background(BLACK);
let w = screen_width(); let h = screen_height();
// Четыре кнопки в ряд — у каждой своя доля ширины экрана и своя ширина. let buttons = [ Rectangle { x: w * 0.05, y: h * 0.35, width: w * 0.15, height: h * 0.3, color: YELLOW }, Rectangle { x: w * 0.28, y: h * 0.35, width: w * 0.22, height: h * 0.3, color: RED }, Rectangle { x: w * 0.58, y: h * 0.35, width: w * 0.15, height: h * 0.3, color: GREEN }, Rectangle { x: w * 0.80, y: h * 0.35, width: w * 0.18, height: h * 0.3, color: PURPLE }, ];
let (mouse_x, mouse_y) = mouse_position(); // Кнопка мыши зажата прямо сейчас. let mouse_down = is_mouse_button_down(MouseButton::Left);
for button in &buttons { // Мышь внутри прямоугольника по обеим осям сразу. let inside = mouse_x >= button.x && mouse_x <= button.x + button.width && mouse_y >= button.y && mouse_y <= button.y + button.height; // Кнопка нажата, только если мышь зажата и попадает внутрь. let pressed = mouse_down && inside;
if pressed { draw_rectangle(button.x, button.y, button.width, button.height, BLUE); } else { draw_rectangle(button.x, button.y, button.width, button.height, button.color); } }
next_frame().await; }}Запусти как обычно:
cargo runЗажми кнопку мыши над любой из четырёх кнопок — она посинеет. Отпусти — вернётся к своему цвету. Попробуй прямо здесь:
Что здесь происходит
Заголовок раздела «Что здесь происходит»struct Rectangle { x, y, width, height, color }— свой тип, описывающий именно прямоугольник, отдельный отCircle: разные формы — разные наборы полей.mouse_x >= button.x && mouse_x <= button.x + button.width— проверка по горизонтали: мышь не левее и не правее прямоугольника.mouse_y >= button.y && mouse_y <= button.y + button.height— та же проверка по вертикали.- Все четыре условия соединены через
&&в одно:insideстановитсяtrue, только если мышь проходит проверку и поx, и поyодновременно — а по каждой оси ещё и сразу с двух сторон. pressed = mouse_down && inside— то же самое объединение, что и в уроке «Круглые кнопки»: нажатой кнопка считается, только если мышь и зажата, и находится внутри.