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

Уроки · 89

Пауза

Давай сделаем паузу: нажал клавишу, и всё замерло, нажал ещё раз, и движение продолжилось с того же места. Нам понадобится одна переменная и одна новая функция.

В уроке «Ввод с клавиатуры» мы проверяли клавишу через is_key_down. Она верна на каждом кадре, пока клавиша зажата. Для паузы это не подходит: человек держит клавишу долю секунды, но за это время проходит несколько кадров, и пауза бы то включалась, то выключалась.

Нам нужна другая функция, is_key_pressed. Она верна только на одном кадре, в момент нажатия. С мышью мы уже так делали: там is_mouse_button_down и is_mouse_button_pressed, как в уроке «Автоматический огонь». С клавишами всё устроено так же:

// Клавишу P только что нажали.
if is_key_pressed(KeyCode::P) {
// Включаем или выключаем паузу.
paused = !paused;
}

paused — переменная типа bool: true, когда игра на паузе, и false, когда нет. Запись paused = !paused переворачивает её значение. ! мы видели в уроке «Порядок отрисовки»: он меняет true на false, а false на true. Нажали P один раз, и пауза включилась. Нажали второй раз, и выключилась.

Паузе нужно остановить движение, а рисование оставить как есть. Поэтому всё, что двигает круг, лежит внутри if !paused { ... }:

// Круг двигается, только пока игра не на паузе.
if !paused {
x += SPEED * dt;
}

Рисуем мы всё равно на каждом кадре, поэтому круг остаётся на экране. А dt каждый кадр считается заново из времени последнего кадра, поэтому после паузы круг продолжает ровно с того места, где остановился, и не прыгает вперёд.

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

src/main.rs
use macroquad::prelude::*;
// Скорость круга в пикселях в секунду.
const SPEED: f32 = 300.0;
#[macroquad::main("Пауза")]
async fn main() {
// Где сейчас круг по горизонтали.
let mut x: f32 = 0.0;
// Игра сейчас на паузе? Сначала нет.
let mut paused = false;
loop {
clear_background(BLACK);
// dt (delta time) — сколько секунд прошло между прошлым кадром и этим.
let dt = get_frame_time();
// Клавишу P только что нажали — включаем или выключаем паузу.
if is_key_pressed(KeyCode::P) {
paused = !paused;
}
// Круг двигается, только пока игра не на паузе.
if !paused {
// Шаг за кадр — скорость, умноженная на dt.
x += SPEED * dt;
// Круг ушёл за правый край — возвращаем к левому.
if x > screen_width() {
x = 0.0;
}
}
// Рисуем круг на каждом кадре, даже на паузе.
draw_circle(x, screen_height() / 2.0, 40.0, YELLOW);
// На паузе пишем об этом в углу.
if paused {
draw_text("Pause", 30.0, 110.0, 100.0, WHITE);
}
next_frame().await;
}
}

Запусти как обычно:

Окно терминала
cargo run

Нажимай P, и круг будет то останавливаться, то снова бежать. Сначала кликни по чёрной области, чтобы нажатия клавиш доходили до неё, как сказано в уроке «Как читать уроки». Попробуй прямо здесь:

  • is_key_pressed(KeyCode::P) верна один кадр, в момент нажатия. А is_key_down верна, пока клавиша зажата.
  • paused — это bool: true, когда игра на паузе. Объявлена она до loop, чтобы помнить своё значение от кадра к кадру.
  • paused = !paused каждым нажатием переворачивает значение на противоположное.
  • if !paused { ... } пропускает движение, пока включена пауза. Рисуется всё по-прежнему на каждом кадре.
  • if paused { draw_text(...) } пишет «Pause» только на паузе. Подпись английская, потому что шрифт по умолчанию не знает русских букв.