## Регистрация персонажей в RPG

Для этого сначала регистрируются "обычные" персонажи (см. Простейшие примеры), которым затем добавляется RPG-функционал.

`$ ch.make_rpg("directory", "rpg_name", "start_dress")`
Где

- `ch` - персонаж, который уже создан (`ch = Character("NewCharacter", color="0x0000FF")`),
- `directory` - часть пути к картинке 240x384, на которой в 4 ряда (строки) расположены 5 кадров (столбцы) на каждый поворот:
  - Кадры (слева на право):
    - 1, 2, 3, 4 - ходьба/бег,
    - 2, 4 - стойка,
    - 5 - сидячее положение.
  - Ряды (сверху вниз):
    - {1, 2, 3, 4} - соответственно {на нас, налево, направо, от нас}.
- `rpg_name` - имя персонажа в пути к RPG-спрайту (вроде me, dv, mt и т. д.),
- `start_dress` - начальная одежда.

Целый путь до картинки вычисляется как `directory + rpg_name + '_' + dress + '.png'`, где `dress` - одежда на персонаже (`'pioneer'`, `'swim'` и т. д.), задаваемая методом `set_dress` (см. отдельный абзац далее).

## Регистрация анимации

    $ register_character_animation(character, "anim_name", "path", xoffset, yoffset,
                                   count_frames, start_frame, end_frame, time = 1.0)

Где

- `character` - персонаж (не имя персонажа), у которого регистрируется анимация,
- `anim_name` - название регистрируемой анимации,
- `path` - путь к изображению (без расширения) анимации (кадры в ряд),
- `xoffset`, `yoffset` - отступ относительно обычного состояния (целые числа),
- `count_frames` - количество кадров в изображении,
- `start_frame` - начальный кадр анимации,
- `end_frame` - последний кадр анимации (включительно),
- `time` - время, за которое анимация будет закончена.

## Запуск анимации

`$ character.start_animation("anim_name", repeat = 0, wait_time = -1)`
Где

- `character` - персонаж,
- `anim_name` - имя зарегистрированной анимации,
- `repeat` определяет кол-во повторов после первого воспроизведения:
  - если `repeat == 0`, повторов не будет,
  - если `repeat < 0`, повторы будут длиться до тех пор, пока анимация не будет удалена или заменена.
- `wait_time` - время (в сек.), на которое выполнение сценария ставится на паузу:
  - Если `wait_time < 0` (по умолчанию), то пауза продлится до тех пор, пока не пройдёт нужное кол-во повторов (если они бесконечны, то ожидания нет).
  - Иначе пауза продлится указанное время. Эту анимацию можно "перемотать", нажав Пробел/Enter или кликнув по фону или кнопке "Далее".

## Удаление анимации

`$ character.remove_animation()`

## Одежда

Смена одежды на `"need_dress"`:
`$ character.set_dress("need_dress")`

## Отображение

Показать персонажа `character` в локации `location` в месте `place_name`:
`$ show_character(character, place_name = None, location = None)`
Если локация не указывается (`None`, по умолчанию), то она принимается за текущую.
Если место не указано, то координаты объекта не меняются (удобно использовать после скрытия, см. далее).

## Скрытие

`$ hide_character(character)`

## "Забыть" персонажа

`$ forget_character(character)`

Создаваемые персонажи кладутся в список, который содержит всех созданных персонажей.
Во время обновления обновляются все персонажи из этого списка, даже если они не находятся на какой-либо локации.
Эта функция удаляет персонажа из этого списка и из локации (если она есть).

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

## Возможность управления

Разрешить или запретить игроку управлять персонажем `me`:
`$ set_rpg_control(value)`
Здесь `value` - `True` (чтобы разрешить) или `False` (запретить).
Получить текущее значение можно функцией `get_rpg_control()`.

## Разрешение на бег

Разрешить/Запретить игроку бег (при управлении с клавиатуры, не касается команд сценария):
`set_run_allow(value)`
Здесь `value` определяет, нужно ли разрешить (`True`) бег или же запретить (`False`).

Узнать, разрешён ли бег: `get_run_allow()`.

## Передвижение персонажа к месту

`$ character.move_to_place("place_name", is_run = False, wait_time = -1, brute_force = False)`
Все аргументы передаются в метод `move_to_places` (см. далее), `place_name` же передаётся в качестве единственного элемента списка мест.
Возвращает значение вызова этого метода.

## Передвижение персонажа по списку мест

`$ character.move_to_places("place_names", is_run = False, wait_time = -1, brute_force = False)`
Где

- `character` - персонаж,
- `place_names` - список мест, которые надо посетить, имеет вид `[("location1", "place1", (-20, 0)), ("location2", "place2"), ...]`:
  - Если его элемент является кортежом размера 3, то в конце указан отступ от места (в пикселях),
  - Если элемент является строкой (а не кортежом), то она считается местом предыдущей локации (а если это первый элемент, то это место текущей локации персонажа),
  - Последний элемент может быть числом - номером места в списке, куда нужно перейти, чтобы ходить "по кругу".
- `is_run` - `True` (бежать) или `False` (идти),
- `wait_time` - время (в сек.), на которое выполнение сценария ставится на паузу:
  - Если `wait_time < 0` (по умолчанию), то пауза продлится до тех пор, пока персонаж не дойдёт до нужного места.
  - Иначе пауза продлится указанное время:
    - Если время уже вышло, а персонаж ещё не дошёл, то происходит переход к следующей команде,
    - Если время ещё не вышло, а персонаж уже дошёл до конца, то пауза всё равно продлится указанное время. Это передвижение можно "перемотать", нажав Пробел/Enter или кликнув по фону или кнопке "Далее",
- `brute_force` - следует ли при поиске пути между точками одной локации искать более короткий путь через выход из этой локации (`False` - нет, быстрый поиск только внутри 1 локации).

Метод возвращает `True`, если удалось найти пути между всеми точками, иначе - `False`. Однако, если какой-то из путей не удалось найти, то персонаж всё равно будет передвигаться напрямую, сквозь все преграды (если точка, до которой не найден путь, на текущей локации) или сразу окажется в конечной точке. Если это поведение нежелательно, то персонажа можно оставить на месте: `character.move_to_place(None)`.

## Поворот

`$ character.set_direction(direction)`
Где

- `character` - персонаж,
- `direction` - направление:
  - `to_forward` (от нас),
  - `to_back` (на нас),
  - `to_left` (влево),
  - `to_right` (вправо). На самом деле `direction` - число, а `to_forward, to_back, to_left, to_right` - переменные, равные `3, 0, 1, 2` соответственно. Однако использовать напрямую числа вместо переменных - плохая идея.

С помощью `character.get_direction()` можно получить текущую сторону поворота. Предполагается, что полученное значение будет сравниваться с переменными `to_forward, to_back, to_left, to_right`.

## Повернуть в сторону объекта

`$ character.rotate_to(obj)`
Где

- `character` - персонаж, которого следует повернуть,
- `obj` - объект, в сторону которого ему нужно повернуться, может быть следующих типов:
  - `Character` (персонаж),
  - `RpgPlace` (место из локации, не путать с названием места),
  - `dict` с параметрами `x` и `y`,
  - Любой другой тип, у которого функция `get_place_center` может извлечь координаты.

Поворот является однократным, т. е. при движении объекта персонаж не будет за ним следить.

## Повернуть по месту

`$ character.rotate_in_place(place = None)`

Здесь `place` - место или имя места, в котором указано, куда повернуть персонажа.
Например, `"washbasin_backward-1"`.
По умолчанию берётся текущее место персонажа.

Если название содержит части `"_left"`, `"_right"`, `"_forward"` или `"_backward"`, то персонаж поворачивается влево, вправо, вперёд (от нас) и назад (на нас) соответственно.

## Смена положения

`$ character.set_pose("pose")`
Где

- `character` - персонаж,
- `pose` - поза, допустимы:
  - `"sit"` - сидеть,
  - `"stay"` - стоять,
  - `"walk"` - идти,
  - `"run"` - бежать.

Узнать текущую позу можно с помощью `character.get_pose()`.

## Сесть

`$ character.sit_down(obj)`
Где `obj` - объект, тип которого является сиденьем.
Сам объект можно получить, например, с помощью этого.
В качестве результата возвращается `True`, если всё прошло успешно, или `False`, если все места уже заняты другими персонажами или объект не является сиденьем.

## Встать

`$ character.stand_up()`
Вызов этого метода для несидящего персонажа не считается ошибкой.

## Наложение

Для "декоративных" целей можно наложить на изображение спрайта персонажа дополнительные изображения.
Это может использоваться, например, для перекрашивания волос и глаз или для добавления шляпы.

Добавление наложения:
`$ character.add_over(images)`
Где `images` - изображение (строка), список изображений, либо функция (принимающая `character` и возвращающая изображение или их список).

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

Удаление наложения:
`$ character.remove_over(images)`
Здесь `images` является тем, что добавляли с помощью `add_over` выше.
Попытка удалить то, что не добавлялось, не считается ошибкой (игнорируется).

Далее ->
<- Назад