Перейти к содержимому

Уроки · 71

Автоинкремент

В уроках «Идентификатор кружка» и «HashMap» все кружки появлялись одной пачкой при старте программы, в одном и том же цикле for i in 0..COUNT. Поэтому ID получался почти бесплатно — это было просто i, которое и так перебирало кружки по порядку. А что, если кружки появляются не пачкой при старте, а по одному — например, каждый клик добавляет новый, и кликов за всю игру может быть сколько угодно?

У такого клика нет своего цикла создания — есть только общий loop игры, а он никак не связан с тем, какой это по счёту кружок. Взять ID оттуда не получится.

Нужна переменная, которая помнит, сколько кружков уже было создано за всю игру, и в любой момент готова выдать следующий свободный номер. Завести её нужно один раз, до loop — по той же причине, по которой до loop объявляется всё, что должно копить значение между кадрами (разбирали в уроке «Изменяемые переменные»):

let mut next_id: u32 = 0;

При создании нового кружка сначала используем текущее значение счётчика как его ID, а сразу после — увеличиваем счётчик на единицу, чтобы следующему кружку досталось число побольше:

circles.insert(next_id, mouse_position());
next_id += 1;

Кликов может быть сколько угодно, а счётчик никогда не обнуляется — каждый новый кружок получает число на единицу больше, чем предыдущий, и так ни один ID не повторится за всю игру, сколько бы она ни продолжалась.

Замени содержимое src/main.rs на это:

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 брался из индекса той же самой пачки, здесь кружки создаются по одному, в случайные моменты — и у счётчика нет привязки ни к какому циклу создания, только к тому, сколько кружков всего появилось за игру.