Перейти к содержанию

Справочник по Pt

Класс Pt — это небольшой помощник, который ведет себя и как 2D-точка, и как очень легкая "черепашка". Он сразу доступен после from drawzero import *. Используйте Pt всякий раз, когда вы хотите сохранить позицию, перемещать ее и передавать в функции рисования из Графические примитивы или Анимации.

Эта страница объясняет полный API Pt простым языком, с множеством коротких примеров, которые вы можете скопировать в интерактивную оболочку или один из примеров скриптов.

Быстрый импорт и первые шаги

from drawzero import *

point = Pt()          # (0, 0) смотрит на восток (направление = 0°)
other = Pt(200, 150)  # x=200, y=150

Pt хранит три значения:

  • x – горизонтальная координата (0 — левый край холста).
  • y – вертикальная координата (0 — верхний край).
  • heading – направление в градусах. 0 означает "смотрит вправо", 90 означает "смотрит вверх".

Все функции рисования принимают объект Pt везде, где они ожидают пару координат. Например:

from drawzero import *

center = Pt(500, 400)
point = Pt(200, 200)

filled_circle('gold', center, 80)
line('black', point, center)  # `line` считывает `(x, y)` из каждого Pt

Создание и чтение точек

Конструкторы

Pt()
Pt(x_value, y_value)
Pt(x_value, y_value, heading=degrees)
  • Все числа могут быть целыми или с плавающей точкой.
  • Если вы опустите heading, DrawZero предполагает 0 градусов.

Получение сохраненных значений

point = Pt(120, 345, heading=30)

point.x        # 120
point.y        # 345
point.heading  # 30

point.pos()       # (120.0, 345.0)
point.position()  # то же, что и pos()
point.xcor()      # 120.0
point.ycor()      # 345.0

Функции xcor/ycor округляют значения до 10 знаков после запятой, чтобы вывод в консоли оставался аккуратным.

Векторная арифметика

Pt ведет себя как изменяемый 2D-вектор. Вы можете складывать, вычитать и масштабировать точки, не написав собственных циклов. Каждая операция создает новый Pt, если она не заканчивается на = (например, +=).

start = Pt(50, 20)
offset = Pt(10, -5)

result = start + offset   # Pt(60, 15, heading=0.0)
start += offset           # start теперь Pt(60, 15, heading=0.0)
mirror = -offset          # Pt(-10, 5, heading=0.0)

Масштабирование работает с обычными числами:

point = Pt(5, 8)
print(point * 3)     # Pt(15, 24, heading=0.0)
print(2 * point)     # Pt(10, 16, heading=0.0)
print(point / 2)     # Pt(2.5, 4.0, heading=0.0)

Когда вам нужна только длина вектора, вызовите abs(point).

hyp = Pt(3, 4)
print(abs(hyp))  # 5.0

Копирование и распаковка

Используйте .copy(), чтобы дублировать точку, сохраняя оригинал без изменений.

head = Pt(100, 100)
shadow = head.copy()
head.forward(50)
# `shadow` все еще помнит старые координаты

Pt также поддерживает распаковку и индексацию:

p = Pt(7, 9)

x, y = p        # итерируется по x, затем y
p[0]            # 7
p[1]            # 9
p[:2]           # [7, 9]
len(p)          # всегда 2

Движение в стиле "черепашки"

Pt хранит угол направления и может двигаться в этом направлении. Это идеально подходит для рисования многоугольников или путей анимации.

walker = Pt()
walker.forward(100)   # движется по направлению (изначально на восток)
walker.right(90)
walker.forward(50)
print(walker.pos())   # (100.0, 50.0)

Ключевые методы и их псевдонимы:

Действие Предпочтительное имя Псевдонимы
Двигаться вперед forward(distance) fd(distance)
Двигаться назад backward(distance) back(distance), bk(distance)
Повернуть направо right(angle) rt(angle)
Повернуть налево left(angle) lt(angle)
Установить направление напрямую setheading(angle) seth(angle)
Сбросить в начало reset() или home()

Направления всегда заворачиваются в диапазон [0, 360).

Пример – функция для рисования правильного многоугольника

from drawzero import *
from math import sin, pi

def regular_polygon(center, sides, radius):
    corner = Pt(center.x, center.y - radius)
    corner.setheading(0)
    angle = 360 / sides
    vertices = []
    for _ in range(sides):
        vertices.append(corner.pos())
        corner.right(angle)
        corner.forward(2 * radius * sin(pi / sides))
    polygon('white', vertices)

regular_polygon(Pt(300, 300), sides=6, radius=120)

polygon взят из Графические примитивы. Pt предоставляет координаты вершин.

Абсолютные перемещения и вращения

Иногда вам нужно перейти к определенному месту или повернуться вокруг другой точки.

  • goto(x, y) / setpos(...) / setposition(...) – перемещение к точным координатам без изменения направления.
  • rotate_around(angle, pivot) – вращение вокруг другого Pt, кортежа или списка.
  • move_towards(distance, target) – перемещение на фиксированное расстояние в направлении другой точки.
p = Pt(100, 100)
p.goto(400, 200)           # -> Pt(400, 200, heading=0.0)
p.rotate_around(90, (200, 200))  # вращение вокруг абсолютной точки
p.move_towards(50, Pt(200, 500))

rotate_around вращает против часовой стрелки, когда угол положительный. Если вам нужен кратчайший путь к цели, move_towards объединяет направление и размер шага для вас.

Функции для расстояния и угла

p = Pt(0, 0)
q = Pt(30, 40)

p.distance(q)      # 50.0
p.towards(q)       # 53.1301023542 градусов
p.is_left_of(10)   # True, потому что 0 < 10
p.is_right_of(-5)  # True, потому что 0 > -5

Функции сравнения используют оси холста:

  • is_above(y_value) возвращает True, если точка выше на экране (меньшее y).
  • is_below(y_value) возвращает True, если точка ниже на экране (большее y).
  • is_left_of(x_value) возвращает True, если x меньше.
  • is_right_of(x_value) возвращает True, если x больше.

Используйте их, чтобы держать спрайты в границах:

ball = Pt(500, -10, heading=90)
if ball.is_above(0):
    ball.flip_vertically()  # отскок от верхнего края

flip_vertically() и flip_horizontally() отражают направление без изменения положения. Это удобно для логики столкновений в небольших играх.

Работа с функциями рисования

Большинство функций рисования принимают объекты Pt напрямую. Вы можете смешивать обычные кортежи и точки в одном вызове.

from drawzero import *

start = Pt(150, 150)
end = Pt(600, 300)

line('cyan', start, end)
rect('orange', start, 200, 120)
filled_circle('white', end, 40)

Для фигур, которые ожидают список вершин (например, polygon или filled_polygon), вызывайте .pos() для каждого Pt.

triangle = [Pt(400, 200), Pt(300, 450), Pt(500, 450)]
polygon('white', [p.pos() for p in triangle])

Чтобы соединить точки с анимацией, объедините эту страницу с Анимации и вызовом tick(), показанным там.

Использование Pt в циклах и анимациях

Pt проявляет себя во всей красе, когда вы обновляете позиции каждый кадр. Пример ниже создает простую орбиту.

from drawzero import *

center = Pt(500, 500)
planet = Pt(650, 500)
planet.setheading(90)

while tick():
    clear()
    filled_circle('navy', center, 40)
    filled_circle('orange', planet, 20)
    planet.rotate_around(3, center)

Прочтите Обзор примеров и откройте 05_points.py или 09_animation_rectangles.py, чтобы увидеть более длинные скрипты, которые используют эти методы вместе.

Советы по устранению неполадок

  • Движение выглядит неправильно? Помните, что начало координат экрана (0, 0) — это верхний левый угол. Движение "вверх" означает уменьшение y.
  • Направление неожиданно скачет? Проверьте, не использовали ли вы backward() или forward() с отрицательными числами. Оба изменяют точку, но сохраняют направление.
  • distance возвращает float со многими десятичными знаками. Это нормально. Используйте round(value, 2) при печати, если хотите меньше цифр.
  • Нужно все сбросить? Вызовите reset() или home(), чтобы установить (x, y) в (0, 0) и heading в 0.

Куда двигаться дальше

  • Графические примитивы – фигуры и текстовые утилиты, которые с радостью принимают объекты Pt.
  • Анимации – как перерисовывать каждый кадр и планировать обновления с помощью tick().
  • Справочник по Gradient – плавные цветовые переходы, которые хорошо сочетаются с движущимися точками.
  • Обзор примеров – таблица скриптов, включая те, которые сосредоточены на Pt.

Поэкспериментируйте с приведенными выше фрагментами, затем смешайте Pt с другими утилитами для создания собственных сцен.