Спрайты
Для поддержки отображения большого количества изображений одновременно Ren'Py поддерживает систему спрайтов. Эта система позволяет создавать спрайты, где каждый спрайт содержит displayable-объект. Затем можно изменять положение спрайтов на экране и их вертикальный порядок.
Если игнорировать производительность, система спрайтов концептуально схожа
с Fixed(), оборачивающим Transform(). Спрайты гораздо
быстрее, чем трансформации, но и менее гибкие. Большое улучшение
производительности спрайтов заключается в том, что каждый displayable-объект
отрисовывается только один раз за кадр, даже если этот displayable-объект используется
многими спрайтами. Ограничение заключается в том, что спрайты позволяют изменять
только их xoffset и yoffset, в отличие от множества свойств,
которые есть у Transform.
Чтобы использовать систему спрайтов, создайте объект SpriteManager, а затем вызовите его метод create для создания новых частиц. По мере необходимости обновляйте поля xoffset, yoffset и zorder каждого спрайта, чтобы перемещать его по экрану. Предоставляя аргументы update и event для SpriteManager, вы можете заставить спрайты меняться со временем и реагировать на ввод пользователя.
Классы спрайтов
- class Sprite
Этот класс представляет спрайт, управляемый SpriteManager. Он содержит поля, которые контролируют размещение спрайта на экране. Спрайты не следует создавать напрямую. Вместо этого их следует создавать, вызывая
SpriteManager.create().Поля объекта Sprite:
- x, y
Координаты x и y верхнего левого угла спрайта относительно SpriteManager.
- zorder
Целое число, которое используется для управления порядком этого спрайта относительно других спрайтов в SpriteManager. Чем больше число, тем ближе к зрителю находится спрайт.
- events
Если True, то события передаются дочернему элементу. Если False (по умолчанию), дочерние элементы игнорируют события (и, следовательно, не тратят время на их обработку).
Методы объекта Sprite:
- destroy()
Уничтожает этот спрайт, предотвращая его отображение и удаляя его из SpriteManager.
- set_child(d)
Изменяет отображаемый объект, связанный с этим спрайтом, на d.
- class SpriteManager(update=None, event=None, predict=None, ignore_time=False, animation=True, **properties)
Этот отображаемый объект управляет коллекцией спрайтов и отображает их с максимально возможной скоростью.
- update
Если не None, это функция, которая вызывается каждый раз, когда спрайт отрисовывается этим менеджером спрайтов. Она вызывается с одним аргументом — временем в секундах с момента первого отображения этого менеджера спрайтов. Ожидается, что она вернет количество секунд до следующего вызова функции, и SpriteManager будет отрисован снова.
- event
Если не None, это функция, которая вызывается при возникновении события. Она принимает следующие аргументы: * Объект события pygame. * Координата x события. * Координата y события. * Время с момента первого показа менеджера спрайтов. Если она возвращает не-None значение, взаимодействие завершается, и это значение возвращается.
- predict
Если не None, это функция, которая возвращает список отображаемых объектов. Эти объекты предсказываются, когда предсказывается и сам менеджер спрайтов.
- ignore_time
Если True, то время игнорируется при отрисовке отображаемых объектов. Это следует использовать, когда менеджер спрайтов используется с относительно небольшим пулом изображений, и эти изображения не изменяются со временем. Это следует использовать только с небольшим количеством отображаемых объектов, так как это будет держать все используемые объекты в памяти на протяжении всей жизни SpriteManager.
- animation
Если True, то этот менеджер спрайтов использует временную шкалу анимации. Это предотвращает его сброс при повторном показе.
После однократной отрисовки (до вызова функции update), SpriteManagers имеют следующие поля:
- width, height
Ширина и высота этого SpriteManager в пикселях.
SpriteManagers имеют следующие методы:
- create(d)
Создает новый спрайт для отображаемого объекта d и добавляет его в этот SpriteManager.
- redraw(delay=0)
Вызывает перерисовку этого SpriteManager через delay секунд.
- SnowBlossom(d, count=10, border=50, xspeed=(20, 50), yspeed=(100, 200), start=0, fast=False, horizontal=False, distribution: Callable[[float, float], float] | str = 'linear', animation=False)
Эффект SnowBlossom перемещает множество экземпляров спрайта вверх, вниз, влево или вправо по экрану. Когда спрайт покидает экран, он возвращается в начальную позицию.
- d
Отображаемый объект, используемый для спрайтов.
- border
Размер рамки экрана. Спрайт считается находящимся на экране до тех пор, пока он не выйдет за рамку, что гарантирует, что спрайты не исчезают внезапно.
- xspeed, yspeed
Скорость, с которой движутся спрайты, в горизонтальном и вертикальном направлениях соответственно. Это может быть одно число или кортеж из двух чисел. В последнем случае каждой частице присваивается случайная скорость между этими двумя числами. Скорости могут быть положительными или отрицательными, главное, чтобы второе число в кортеже было больше первого.
- start
Задержка в секундах перед добавлением каждой частицы. Это позволяет частицам начинать движение с верхней части экрана, не создавая эффекта "волны".
- fast
Если true, частицы начинают движение из центра экрана, а не только с краев.
- horizontal
Если true, частицы появляются с левой или правой стороны экрана, а не сверху или снизу.
- distribution
Функция или имя встроенной функции распределения для определения начальной позиции частицы.
Если это строка, она должна быть одной из следующих: - linear: Значение имеет равные шансы оказаться в любой точке вдоль оси. - gaussian: Значение с большей вероятностью будет находиться ближе к центру и с меньшей — ближе к краям. - arcsine: Значение с большей вероятностью будет находиться ближе к краям и с меньшей — ближе к центру.
Если это функция, она должна принимать два float в качестве аргументов и возвращать float.
По умолчанию — linear.
- animation
Если True, то этот SnowBlossom использует временную шкалу анимации. Это предотвращает его сброс при повторном показе.
Примеры спрайтов
Класс SnowBlossom — это простой в использовании способ размещения падающих объектов на экране.
image snow = SnowBlossom("snow.png", count=100)
Этот пример показывает, как SpriteManager можно использовать для создания сложного поведения. В данном случае он показывает 400 частиц и заставляет их избегать указателя мыши.
init python:
import math
def repulsor_update(st):
# If we don't know where the mouse is, give up.
if repulsor_pos is None:
return .01
px, py = repulsor_pos
# For each sprite...
for i in repulsor_sprites:
# Compute the vector between it and the mouse.
vx = i.x - px
vy = i.y - py
# Get the vector length, normalize the vector.
vl = math.hypot(vx, vy)
if vl >= 150:
continue
# Compute the distance to move.
distance = 3.0 * (150 - vl) / 150
# Move
i.x += distance * vx / vl
i.y += distance * vy / vl
# Ensure we stay on the screen.
if i.x < 2:
i.x = 2
if i.x > repulsor.width - 2:
i.x = repulsor.width - 2
if i.y < 2:
i.y = 2
if i.y > repulsor.height - 2:
i.y = repulsor.height - 2
return .01
# On an event, record the mouse position.
def repulsor_event(ev, x, y, st):
store.repulsor_pos = (x, y)
label repulsor_demo:
python:
# Create a sprite manager.
repulsor = SpriteManager(update=repulsor_update, event=repulsor_event)
repulsor_sprites = [ ]
repulsor_pos = None
# Ensure we only have one smile displayable.
smile = Image("smile.png")
# Add 400 sprites.
for i in range(400):
repulsor_sprites.append(repulsor.create(smile))
# Position the 400 sprites.
for i in repulsor_sprites:
i.x = renpy.random.randint(2, 798)
i.y = renpy.random.randint(2, 598)
del smile
del i
# Add the repulsor to the screen.
show expression repulsor as repulsor
"..."
hide repulsor
# Clean up.
python:
del repulsor
del repulsor_sprites
del repulsor_pos