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

Уроки · 80

if как значение

Давай сделаем так, чтобы ветки if не рисовали, а только выбирали цвет. В уроке «Радиус обнаружения» турель рисовалась в каждой ветке отдельно:

if player_distance < RADIUS {
// Игрок внутри радиуса — красная турель.
draw_circle(center_x, center_y, 40.0, RED);
} else {
// Игрок снаружи — синяя турель.
draw_circle(center_x, center_y, 40.0, BLUE);
}

Ветки отличаются только цветом, а остальное в них повторяется. Давай выберем цвет один раз, а нарисуем после.

if с else целиком можно считать значением: какая ветка сработала, то и получится. Это значение можно положить в переменную:

// Ветки выбирают цвет. Что выбрала сработавшая, то и попадёт в color.
let color = if player_distance < RADIUS { RED } else { BLUE };
// Рисуем один раз, цветом из переменной.
draw_circle(center_x, center_y, 40.0, color);

Мы уже видели такое в уроке «Свои функции»: там if с else стоял последним в функции, и то, что выбрала ветка, функция отдавала наружу. Здесь то же самое, только результат уходит не из функции, а в переменную color.

  • В обеих ветках значения одного типа: RED и BLUE оба цвета. Цвет в одной ветке и число в другой не получится.
  • В конце ветки точку с запятой не ставим. Если поставить, ветка ничего не отдаст.
  • else обязателен. Без него не сказано, что отдавать, когда условие неверно.

Выгода не только в том, что код короче. Выбранный цвет можно использовать сколько угодно раз, не повторяя условие. В демо ниже color красит и турель, и контур радиуса: решение принято один раз, а работает в двух местах.

Белый кружок под курсором — игрок. Заведи его внутрь контура: и турель, и контур покраснеют разом, потому что цвет выбран один раз. Меняй радиус ниже:

src/main.rs
use macroquad::prelude::*;
// Радиус один и тот же на каждом кадре, поэтому это константа
// (как в уроке «Константы»), а не переменная внутри loop.
const RADIUS: f32 = 300.0;
// Своя функция: расстояние между двумя точками, как в уроке «Расстояние».
fn distance(from_x: f32, from_y: f32, to_x: f32, to_y: f32) -> f32 {
let dx = to_x - from_x;
let dy = to_y - from_y;
(dx * dx + dy * dy).sqrt()
}
#[macroquad::main("if как значение")]
async fn main() {
loop {
clear_background(BLACK);
// Центр экрана — здесь же стоит турель.
let center_x = screen_width() / 2.0;
let center_y = screen_height() / 2.0;
// Координаты курсора.
let (mouse_x, mouse_y) = mouse_position();
// Расстояние от турели до курсора.
let player_distance = distance(center_x, center_y, mouse_x, mouse_y);
// if с else выдаёт значение: что выбрала сработавшая ветка, то и
// попадёт в color. Игрок внутри радиуса — красный, иначе синий.
// После RED и BLUE точку с запятой не ставим.
let color = if player_distance < RADIUS { RED } else { BLUE };
// Контур — радиус обнаружения, того же цвета, что и турель.
draw_circle_lines(center_x, center_y, RADIUS, 3.0, color);
// Турель.
draw_circle(center_x, center_y, 40.0, color);
// Игрок — кружок под курсором.
draw_circle(mouse_x, mouse_y, 25.0, WHITE);
next_frame().await;
}
}
  • let color = if player_distance < RADIUS { RED } else { BLUE }; — if с else выдаёт значение. Сработала первая ветка, и в color попадает RED, сработала вторая, и BLUE.
  • distance — своя функция расстояния между двумя точками, как в уроке «Расстояние», только вынесенная из main, как в уроке «Свои функции». Результат записан в player_distance.
  • RED и BLUE стоят в ветках без точки с запятой: так ветка отдаёт значение наружу.
  • color используется дважды: для контура радиуса и для самой турели. Условие при этом проверено только один раз.
  • if как значение работает не только для цветов, но и для любых значений: чисел, координат, чего угодно, лишь бы в обеих ветках был один и тот же тип.