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

Уроки · 53

Спутник

В уроке «Вращение» разобрались, как крутить вектор вокруг нуля — angle.cos() и angle.sin() дают его направление, а рост angle каждый кадр заставляет его вращаться. Применим это на деле — сделаем маленький кружок, вращающийся вокруг большого, как спутник вокруг планеты. Разница только в одном: направление теперь нужно не просто нарисовать из нуля, а прибавить к центру — тем же приёмом сложения, что и в уроке «Точка плюс вектор», — тогда вращаться будет вокруг центра, а не вокруг нуля.

// Точка — как в уроке «Точка и прямоугольник».
struct Point {
x: f32,
y: f32,
}
// Точка на окружности радиусом radius вокруг center, под углом angle.
fn orbit(center: Point, radius: f32, angle: f32) -> Point {
// Единичный вектор — направление длиной 1, вычисленное прямо из угла.
let direction_x = angle.cos();
let direction_y = angle.sin();
// Растягиваем направление до длины radius и прибавляем к center —
// тот же приём сложения, что и в «Точке плюс вектор».
Point {
x: center.x + direction_x * radius,
y: center.y + direction_y * radius,
}
}

Маленький кружок вращается вокруг большого с постоянной угловой скоростью. Поменяй speed ниже:

src/main.rs
use macroquad::prelude::*;
// Точка — как в уроке «Точка и прямоугольник».
struct Point {
x: f32,
y: f32,
}
// Точка на окружности радиусом radius вокруг center, под углом angle.
fn orbit(center: Point, radius: f32, angle: f32) -> Point {
// Единичный вектор — направление длиной 1, вычисленное прямо из угла.
let direction_x = angle.cos();
let direction_y = angle.sin();
// Растягиваем направление до длины radius и прибавляем к центру —
// получаем точку на самой окружности (тот же приём сложения, что и
// в уроке «Смещение»).
Point {
x: center.x + direction_x * radius,
y: center.y + direction_y * radius,
}
}
// speed одна и та же на каждом кадре, поэтому это константа (как в
// уроке «Константы»), а не переменная внутри loop.
const SPEED: f32 = 0.020;
#[macroquad::main("Спутник")]
async fn main() {
// Угол растёт каждый кадр — mut и вне loop, чтобы помнить прошлый кадр.
let mut angle: f32 = 0.0;
loop {
clear_background(BLACK);
let center = Point { x: screen_width() / 2.0, y: screen_height() / 2.0 };
// Большой кружок в центре — «планета».
draw_circle(center.x, center.y, 40.0, DARKBLUE);
// Маленький кружок на орбите вокруг центра.
let point = orbit(center, 150.0, angle);
draw_circle(point.x, point.y, 16.0, YELLOW);
// Угол растёт на фиксированную угловую скорость каждый кадр.
angle += SPEED;
next_frame().await;
}
}
  • orbit(center, radius, angle) — считает точку на окружности в два шага: сперва направление (direction_x, direction_y) вокруг нуля, затем растягивает его до radius и прибавляет center — то же сложение, что и в уроке «Смещение».
  • angle растёт на фиксированную величину каждый кадр — mut и вне loop, ровно как позиция в уроке «Погоня за мышью».
  • Из-за перевёрнутой оси y (как в уроке «Координаты») вращение на экране идёт по часовой стрелке.
  • speed в коде — const SPEED, а не переменная внутри loop: значение одно и то же на каждом кадре, пока ты сам его не изменишь, поэтому это константа, как в уроке «Константы».