Уроки · 36
Разноцветные кружки
В уроке «Список кружков» мы научились работать с Vec —
списком, который растёт сам, пока работает программа. Но набор цветов,
из которых выбираем, никогда не меняется — он известен заранее, раз и
навсегда. Заводить для него растущий Vec было бы избыточно: цвета
никогда не добавляются и не убираются, а вся гибкость Vec тут просто
не нужна. Гораздо проще — массив: список с длиной, зафиксированной
раз и навсегда, прямо в типе.
Массив цветов
Заголовок раздела «Массив цветов»const COLORS: [Color; 4] = [YELLOW, RED, GREEN, BLUE];Тип массива, [Color; 4], похож на Vec<T> из прошлого урока — тоже
говорит, какого типа элементы внутри, — только скобки квадратные, а не
угловые, и, кроме типа элемента, через точку с запятой указано ещё и
само количество: ровно 4, не больше и не меньше. Это число — часть
типа, зашитая в код так же, как COUNT в уроке «Сколько угодно
кружков»: оно не может увеличиться, пока программа
работает.
Справа от = — уже готовое значение: те же квадратные скобки, но на
этот раз в них перечислены сами элементы через запятую,
[YELLOW, RED, GREEN, BLUE] — их ровно столько, сколько сказано в
типе.
Color — тип, который у нас давно на виду: это тип значений вроде
YELLOW и BLACK, просто раньше не было повода называть его по
имени.
У массива есть метод .len() — он возвращает, сколько элементов
внутри. Число 4 в типе [Color; 4] всё-таки пришлось написать
руками — это часть объявления массива, тут никуда не деться. Но это
единственное место, где оно встречается: .len() в остальном коде
читает длину прямо из COLORS, а не хранит её отдельно, как хранил
бы отдельный const COUNT. Добавишь пятый цвет — поправишь только
[Color; 4] на [Color; 5], а .len() везде сам вернёт уже новое
число, без правок где-либо ещё.
Случайный индекс
Заголовок раздела «Случайный индекс»У каждого элемента массива есть свой номер по порядку, начиная с 0
— он называется индексом. Раньше rand::gen_range выбирал
случайную координату на экране (в уроке «Случайная
точка»). Здесь тот же gen_range выбирает случайный
индекс — число от 0 до COLORS.len() - 1, тот же принцип «до, но не
включая», что и в 0..COUNT из урока «Сколько угодно
кружков»:
let index = rand::gen_range(0, COLORS.len());let color = COLORS[index];COLORS[index] — доступ к элементу массива по индексу: число в
квадратных скобках после названия массива и есть номер элемента,
который нужно взять. Здесь это ровно тот случайно выбранный цвет.
Замени содержимое src/main.rs на это:
use macroquad::prelude::*;
// Фиксированный список цветов, из которого выбираем случайный.const COLORS: [Color; 4] = [YELLOW, RED, GREEN, BLUE];
#[macroquad::main("Разноцветные кружки")]async fn main() { // Список кружков: координаты клика и выбранный для него цвет. let mut circles: Vec<(f32, f32, Color)> = Vec::new();
loop { clear_background(BLACK);
// Кнопка мыши только что нажата — новый кружок со случайным цветом. if is_mouse_button_pressed(MouseButton::Left) { let (x, y) = mouse_position(); // Случайный индекс от 0 до длины списка COLORS. let index = rand::gen_range(0, COLORS.len()); circles.push((x, y, COLORS[index])); }
// Рисуем каждый кружок его собственным цветом. for &(x, y, color) in &circles { draw_circle(x, y, 20.0, color); }
next_frame().await; }}Запусти как обычно:
cargo runКликай по экрану — каждый новый кружок получает случайный цвет из четырёх заданных. Попробуй прямо здесь:
Что здесь происходит
Заголовок раздела «Что здесь происходит»const COLORS: [Color; 4] = [...]— массив из четырёх цветов, собранных в одном месте, а не в четырёх отдельных переменных.COLORS.len()— длина массива,4, взятая из самого массива, а не прописанная отдельно.rand::gen_range(0, COLORS.len())возвращает случайный индекс от0доCOLORS.len() - 1— та же функция, что и раньше, просто диапазон теперь подобран под размер массива.COLORS[index]— доступ к элементу массива по индексу, тот самый случайно выбранный цвет.Vec<(f32, f32, Color)>— кортеж вырос до трёх элементов: теперь каждый кружок хранит ещё и свой цвет вместе с координатами.