-
Notifications
You must be signed in to change notification settings - Fork 0
Сигналы и таймауты
С помощью сигналов можно реагировать на определённые события (и/или запускать их самостоятельно).
Таймауты позволяют вызвать какую-либо функцию через определённое время.
Интервалы позволяют вызывать функцию через определённые промежутки времени.
Всё это работает на уровне питона, т. е. должно быть либо в блоке python
, либо в команде $
.
Добавить реакцию на сигнал "event" - выполнить функцию function
:
signals.add("event", function, priority = 0, times = -1)
Если на одно событие повешено несколько функций, то сначала выполнится та, что с меньшим приоритетом.
Если 2 функции имеют одинаковый приоритет, то первой будет первая добавленная.
times
определяет число вызовов, после которого эта функция будет удалена из реакций на данное событие (-1
- никогда не удалять).
Пример:
def my_function(arg = "world"):
out_msg("Hello, %s!" % arg)
signals.add("my_super_event", my_function)
Удалить реакцию на событие "event":
signals.remove("event", function)
Здесь function
- функция, указанная ранее в signals.add
.
Отправить сигнал (вызвать все функции, подписанные на "event"):
signals.send("event", *args, **kwargs)
2 последние аргумента обозначают, что вы можете добавлять какие-угодно аргументы, и они будут переданы вызываемым функциям.
Например: signals.send("my_super_event", "My Super World")
Или даже с именованым параметром: signals.send("my_super_event", arg="another world")
При отправке сигнала все функции, реагирующие на этот сигнал, вызываются сразу же.
Список стандартных сигналов - в конце.
Таймауты и интервалы работают примерно также, как и в JS (javascript
в вашем браузере).
Вызвать function
через time_sec
секунд (может быть нецелым числом):
my_id = set_timeout(function, time_sec)
Результат - идентификатор таймаута (его номер), через который его можно отменить (и это единственный способ сделать это).
Отменить вышеуказанную операцию:
clear_timeout(my_id)
Если вызвать эту функцию несколько раз для одного и того же идентификатора, то это не будет считаться ошибкой.
Интервалы очень похожи на таймауты, но указанная функция вызывается не 1 раз, а постоянно через указанные промежутки времени:
my_id = set_interval(function, time_sec)
Отмена:
clear_interval(my_id)
Вместо функций могут приниматься вызываемые (callable
) объекты, в том числе такие как Function
, AddVariable
, SetDict
и т. д.
Однако следует помнить, что все эти функции должны где-то храниться, а значит и уметь сохраняться и восстанавливаться с помощью pickle
.
Причём проверка на это занимает какое-то время, так что делать это по тысяче раз за кадр - плохая идея.
Впрочем, проверку можно временно отключить, вызвав
signals.set_check_picklable(False)
Тогда после включения (True
вместо False
в примере выше)
будут проверены все новые объекты сразу, что будет в десятки раз быстрее.
Функции таймаутов никогда не выполнятся сразу же - только в следующем кадре, даже если указано выполнить их через 0
секунд.
Таймауты и интервалы реализованы через сигналы, конкретно - через "enter_frame".
Поэтому их точность зависит от текущего FPS (кол-ва кадров в секунду).
При максимальном FPS (60
) можно рассчитывать на максимальную точность в 16.7
милисекунды (если не будет зависаний по каким-либо причинам).
Таким образом, нельзя рассчитывать на то, что нужные функции будут вызваны милисекунда в милисекунду (или даже в нужный десяток милисекунд). Также интервал будет вызван между 2 соседними кадрами не более одного раза.
Непонятно зачем, но если вдруг есть реальная причина, то можно создать собственный экземпляр сигналов,
полностью независимый от стандартного: my_signals = Signals()
Разумеется, при отправке событий в стандартные сигналы, ваши не будут их получать (на то он и полностью независимый).
Общие:
-
"enter_frame"
- "вход" в кадр (перед отрисовкой скринов), -
"exit_frame"
- "выход" из кадра (после отрисовки всех скринов), -
"show_screen"
- на экран добавлен какой-то скрин (функция должна принимать 1 аргумент - название скрина), -
"hide_screen"
- с экрана был скрыт какой-то скрин (функция должна принимать 1 аргумент - название скрина), -
"resized_stage"
- размер окна был изменён (см. функциюget_stage_size
).
РПГ-часть:
-
"rpg-location"
- игрок перешёл из одной локации в другую (см. переменныеcur_location
иcur_location_name
), -
"rpg-place"
- игрок вошёл в определённое место на локации (см.cur_place
иcur_place_name
), -
"rpg-no_exit"
- игрок попытался перейти туда, куда у него нет доступа (см. систему запретов в РПГ), -
"rpg-stand_up"
- игрок встал, -
"rpg-sit_down"
- игрок сел, -
"rpg-action"
- нажата "кнопка действия".
Инвентарь РПГ-части (функция должна принимать 1 аргумент - название объекта):
-
"inventory-remove"
- выбрасывание предмета из инвентаря, -
"inventory-use"
- использование предмета в инвентаре, -
"inventory-take"
- взятие предмета в инвентарь.
Прочее:
-
"time"
- изменено время суток (функция должна принимать название нового времени суток), -
"language"
- был установлен язык игры (см. Система переводов).
Основы
Если вы новичок, то будет достаточно прочитать лишь это, пока ваш энтузиазм не исчерпан.
Остальное можно будет прочесть по мере надобности.
Документация по RPG-части находится здесь.
Более сложные вещи
Через некоторое время вам, возможно, потребуются более продвинутые возможности.
- Функции для изображений (im-функции).
- Эффекты.
- Времена суток.
- ATL (анимации и трансформации).
- Ввод с клавиатуры.
- Введение в ScreenLang (GUI, интерфейс).
- Конфигурирование игры.
Дополнительно
- Некоторые полезные функции.
- Сигналы и таймауты.
- Технические подробности работы с изображениями.
- Технические подробности ВН-спрайтов.
- Система переводов.
- Воспроизведение видео.
- Скрин помощи.
- Прерываемые циклы.
- https.
- Система обновлений.
Перед самым началом
Советы для новичков и не только.
Оффтоп.