Домашний проект D: отскакивающие мячи с Pygame
Позиция и скорость хранятся в Vector2, а движение учитывает dt. Скорость измеряется в единицах за секунду, а не за кадр.
Мяч описан классом Myach. Позиция и скорость хранятся как
pygame.Vector2, а скорость измеряется в пикселях в
секунду, а не в пикселях за кадр:
class Myach:
def __init__(self, x, y, vx, vy, radius, cvet):
self.pos = Vector2(x, y)
self.velocity = Vector2(vx, vy) # пикселей в секунду
self.radius = radius
self.cvet = cvet
self.otskokov = 0
def shag(self, dt: float) -> None:
self.pos += self.velocity * dt
if self.pos.x - self.radius < 0 or self.pos.x + self.radius > SHIRINA:
self.velocity.x = -self.velocity.x
self.otskokov += 1
# ...то же самое для self.pos.y и VYSOTA
dt (реального времени, прошедшего с прошлого кадра), мяч на экране с частотой 120 кадров в секунду улетит вчетверо дальше за одну и ту же секунду, чем на 30 кадрах в секунду. Умножение на dt выражает скорость в единицах за секунду и сильно уменьшает зависимость от FPS. Свободное равномерное движение совпадает при разных FPS в пределах численной точности, но дискретное обнаружение столкновений всё ещё может зависеть от размера шага времени.Окно и цикл отрисовки создаются только внутри main().
импорт файла bouncing_balls.py не открывает окно pygame, а
значит, Myach.shag() можно проверить тестом без дисплея:
def main() -> None:
pygame.init()
screen = pygame.display.set_mode((SHIRINA, VYSOTA))
clock = pygame.time.Clock()
myachi = sozdat_myachi()
while rabotaet:
dt = clock.tick(FPS) / 1000
for myach in myachi:
myach.shag(dt)
narisovat_kadr(screen, myachi)
Полный код: projects/pygame/bouncing-balls-oop/bouncing_balls.py
Задание
Для учебного упрощения рассматривайте только лобовое столкновение одинаковых мячей: центры и скорости лежат на одной прямой, мячи сближаются. В этом ограниченном случае обменяйте velocity целиком. Не выдавайте этот приём за общую формулу 2D-столкновения.
Issue «Add bouncing balls project», ветка feat/bouncing-balls,
тест на независимость движения от FPS (30/60/120 кадров дают одинаковый результат за одну и
ту же секунду), Pull Request.