Уроки · 71
Автоинкремент
В уроках «Идентификатор кружка» и «HashMap»
все кружки появлялись одной пачкой при старте программы, в одном и том же
цикле for i in 0..COUNT. Поэтому ID получался почти бесплатно — это было
просто i, которое и так перебирало кружки по порядку. А что, если
кружки появляются не пачкой при старте, а по одному — например, каждый
клик добавляет новый, и кликов за всю игру может быть сколько угодно?
У такого клика нет своего цикла создания — есть только общий loop игры,
а он никак не связан с тем, какой это по счёту кружок. Взять ID оттуда
не получится.
Отдельный счётчик для ID
Заголовок раздела «Отдельный счётчик для ID»Нужна переменная, которая помнит, сколько кружков уже было создано за всю
игру, и в любой момент готова выдать следующий свободный номер. Завести
её нужно один раз, до loop — по той же причине, по которой до loop
объявляется всё, что должно копить значение между кадрами (разбирали в
уроке «Изменяемые переменные»):
let mut next_id: u32 = 0;При создании нового кружка сначала используем текущее значение счётчика как его ID, а сразу после — увеличиваем счётчик на единицу, чтобы следующему кружку досталось число побольше:
circles.insert(next_id, mouse_position());next_id += 1;Кликов может быть сколько угодно, а счётчик никогда не обнуляется — каждый новый кружок получает число на единицу больше, чем предыдущий, и так ни один ID не повторится за всю игру, сколько бы она ни продолжалась.
Замени содержимое src/main.rs на это:
use macroquad::prelude::*;use std::collections::HashMap;
// Радиус один и тот же у всех кружков — фиксированный, как в уроке «Константы».const RADIUS: f32 = 60.0;
#[macroquad::main("Автоинкремент")]async fn main() { // Кружки, появляющиеся по клику: ключ — ID, значение — координаты. let mut circles: HashMap<u32, (f32, f32)> = HashMap::new(); // Следующий свободный ID — растёт на единицу с каждым новым кружком. let mut next_id: u32 = 0;
loop { clear_background(BLACK);
// Кнопка мыши только что нажата — добавляем новый кружок. if is_mouse_button_pressed(MouseButton::Left) { // Текущее значение счётчика становится ID нового кружка. circles.insert(next_id, mouse_position()); // Следующий кружок получит число на единицу больше. next_id += 1; }
// Рисуем каждый кружок и подписываем его ID. for (&id, &(x, y)) in &circles { draw_circle(x, y, RADIUS, YELLOW); draw_text(&id.to_string(), x, y, 64.0, BLACK); }
next_frame().await; }}Запусти как обычно:
cargo runКликай по экрану — каждый клик добавляет новый кружок со своим номером, и номера всё время растут, сколько бы кружков ты уже успел наставить. Попробуй сам:
Что здесь происходит
Заголовок раздела «Что здесь происходит»let mut next_id: u32 = 0;объявлена один раз, доloop— как иxв уроке «Изменяемые переменные»: эта переменная должна помнить своё значение между кадрами, а не создаваться заново каждый раз.circles.insert(next_id, ...)использует текущее значение счётчика как ID нового кружка.next_id += 1;сразу после — следующий кружок получит число на единицу больше.- В отличие от уроков «Идентификатор кружка» и «HashMap», где кружки создавались пачкой и ID брался из индекса той же самой пачки, здесь кружки создаются по одному, в случайные моменты — и у счётчика нет привязки ни к какому циклу создания, только к тому, сколько кружков всего появилось за игру.