Уроки · 39
Порядок отрисовки
Присмотрись к демке в уроке «Радиус мышью»: пока тянешь радиус, жёлтый превью-кружок рисуется под уже сохранёнными кружками. Но стоит отпустить кнопку — новый кружок оказывается поверх всех остальных. Это не случайность и не баг — так работает отрисовка в целом.
Рисование — это как кисть
Заголовок раздела «Рисование — это как кисть»draw_circle и любая другая функция рисования — draw_rectangle,
draw_line, draw_text — ведут себя как мазок кистью по холсту:
закрашивают те пиксели, куда попадают, поверх всего, что там уже было
нарисовано раньше. Экран — это не набор именованных фигур, которые
помнят, кто где лежит, а просто изображение, которое каждый кадр
рисуется заново, мазок за мазком, сверху вниз по коду.
Значит, то, что нарисовано позже, всегда оказывается видно сверху — независимо от того, где фигура находится на экране или в каком месте массива или списка лежит.
Запоминаем порядок
Заголовок раздела «Запоминаем порядок»Чтобы по клику менять порядок рисования, нужно где-то хранить, какой
он сейчас. Для значения, у которого всего два варианта — да или нет —
в Rust есть тип bool, а сами варианты называются true и false:
let mut small_on_top = true;Перевернуть такое значение на противоположное можно знаком ! перед
ним: было true — станет false, и наоборот.
small_on_top = !small_on_top;Замени содержимое src/main.rs на это:
use macroquad::prelude::*;
#[macroquad::main("Порядок отрисовки")]async fn main() { // Кто рисуется вторым — и поэтому окажется сверху. let mut small_on_top = true;
loop { clear_background(BLACK);
// Клик — меняем местами порядок отрисовки. if is_mouse_button_pressed(MouseButton::Left) { small_on_top = !small_on_top; }
// Центр экрана — оба круга рисуются в одной точке. let center_x = screen_width() / 2.0; let center_y = screen_height() / 2.0;
if small_on_top { // Большой круг первым, маленький вторым — маленький виден поверх. draw_circle(center_x, center_y, 80.0, BLUE); draw_circle(center_x, center_y, 35.0, YELLOW); } else { // Маленький круг первым, большой вторым — маленький скрыт под ним. draw_circle(center_x, center_y, 35.0, YELLOW); draw_circle(center_x, center_y, 80.0, BLUE); }
next_frame().await; }}Запусти как обычно:
cargo runДва круга рисуются в одной точке — большой синий и маленький жёлтый. Кликни — и они поменяются местами: тот же самый жёлтый кружок то видно целиком, то не видно совсем. Ни размер, ни положение кругов при этом не меняются — только порядок, в котором их рисует код. Попробуй прямо здесь:
Что здесь происходит
Заголовок раздела «Что здесь происходит»is_mouse_button_pressed(...)тоже возвращаетbool— мы просто никогда раньше не сохраняли такое значение в свою переменную, только сразу проверяли вif.- Клик переворачивает
small_on_topчерез!и сразу присваивает обратно в неё же — тем самым меняя местами два вызоваdraw_circleвнутриif. - Круги остаются на тех же местах с теми же радиусами весь урок — меняется только порядок двух строк кода, и этого достаточно, чтобы поменять, кто кого закрывает.
- В уроке «Свои структуры» то же самое происходило
неявно:
for circle in &circlesрисует кружки в том порядке, в котором они лежат вVec— то есть в порядке, в каком были добавлены через.push. Последний добавленный рисуется последним, а значит — оказывается сверху.