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

Уроки · 81

Полоска здоровья

Давай нарисуем полоску здоровья. Для неё хватит двух прямоугольников, которые мы уже умеем рисовать по уроку «Прямоугольник».

Первая, серая, рисуется целиком: она показывает всё здоровье, которое вообще может быть. Вторая, зелёная, лежит поверх неё и показывает, сколько здоровья осталось. Её рисуем позже серой, поэтому она оказывается сверху, как в уроке «Порядок отрисовки».

Обе полоски начинаются в одном месте и одной высоты. Отличается только ширина: у зелёной она зависит от здоровья.

Чтобы найти ширину зелёной полоски, нужна доля здоровья от 0 до 1, как в уроке «Доля от 0 до 1». Делим текущее здоровье на максимальное. Осталось 50 из 100, значит доля равна 0.5, и зелёная полоска вдвое короче серой. Это те же проценты из урока «Проценты», только поделённые на сто.

// Доля здоровья от 0 до 1: осталось 50 из 100 — получится 0.5.
let fraction = health / MAX_HEALTH;
// Серая подложка — вся полоска целиком.
draw_rectangle(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT, GRAY);
// Зелёная часть — столько от всей ширины, сколько осталось здоровья.
draw_rectangle(BAR_X, BAR_Y, BAR_WIDTH * fraction, BAR_HEIGHT, GREEN);

Текущее здоровье меняется, поэтому это переменная с mut, как в уроке «Изменяемые переменные». Клик, как в уроке «Клик мышью», отнимает DAMAGE. Когда здоровья уже нет, следующий клик возвращает полное. Так полоска успевает показать «пусто», а не перескакивает сразу на максимум:

if health <= 0.0 {
// Здоровья уже нет — возвращаем полное.
health = MAX_HEALTH;
} else {
// Отнимаем урон. max(0.0) не даёт здоровью уйти ниже нуля.
health = (health - DAMAGE).max(0.0);
}

.max(0.0) берёт большее из двух чисел, как в уроке «Радиус мышью». Если поменять DAMAGE на число, которое не делит 100 нацело, без этого здоровье ушло бы ниже нуля, а ширина зелёной полоски стала бы отрицательной.

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

src/main.rs
use macroquad::prelude::*;
// Здоровье в начале и его максимум.
const MAX_HEALTH: f32 = 100.0;
// Сколько здоровья отнимает один клик.
const DAMAGE: f32 = 10.0;
// Левый верхний угол полоски, её высота и длина.
const BAR_X: f32 = 20.0;
const BAR_Y: f32 = 20.0;
const BAR_HEIGHT: f32 = 40.0;
const BAR_WIDTH: f32 = 400.0;
#[macroquad::main("Полоска здоровья")]
async fn main() {
// Текущее здоровье — сначала полное.
let mut health = MAX_HEALTH;
loop {
clear_background(BLACK);
// Кнопка мыши только что нажата.
if is_mouse_button_pressed(MouseButton::Left) {
if health <= 0.0 {
// Здоровья уже нет — возвращаем полное.
health = MAX_HEALTH;
} else {
// Отнимаем урон. max(0.0) не даёт здоровью уйти ниже нуля.
health = (health - DAMAGE).max(0.0);
}
}
// Доля здоровья от 0 до 1.
let fraction = health / MAX_HEALTH;
// Серая подложка: вся полоска целиком.
draw_rectangle(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT, GRAY);
// Зелёная часть поверх неё: ширина — доля от всей полоски.
draw_rectangle(BAR_X, BAR_Y, BAR_WIDTH * fraction, BAR_HEIGHT, GREEN);
next_frame().await;
}
}
  • MAX_HEALTH, DAMAGE и размеры полоски — константы, как в уроке «Константы»: они не меняются от кадра к кадру.
  • health — текущее здоровье. Это единственное, что меняется в программе.
  • fraction = health / MAX_HEALTH — доля здоровья от 0 до 1. По ней считается ширина зелёной полоски.
  • Серый прямоугольник шириной BAR_WIDTH рисуется целиком, а зелёный шириной BAR_WIDTH * fraction рисуется поверх него.
  • На клик здоровье уменьшается на DAMAGE, а когда оно кончилось, возвращается к максимуму.
  • .max(0.0) не даёт здоровью стать отрицательным.