## Пользовательские классы

Разработчик игры (т. е. пользователь Ren-Engine) может использовать свои классы для rpg-объектов со своим поведением, специфическим для его игры.

Для этого такие классы должны удовлетворять некоторым требованиям:
1. Конструктор (`__init__`) помимо `self` принимает ещё и параметры `xpos, ypos, xsize, ysize, **kwargs` (позицию, размеры и словарь параметров),
разумеется, любые эти параметры можно запомнить, проигнорировать или использовать для каких-то своих вычислений,
2. Опционально может присутствовать метод `free`, возвращающий полный путь (или результат `im`-функции) к карте непроходимости,
составленной по принципам обычных объектов локаций,
3. Метод `update`, вызываемый для обновления объекта перед отрисовкой,
4. Метод `get_draw_data(self)`, возвращающий данные для отрисовки.
Результатом должен быть словарь (`dict`) или список из нескольких словарей со свойствами:
	* `image`  - путь к изображению или результат `im`-функции,
	* `pos`    - кортёж или список из `x`- и `y`-координат; дальнейшие параметры не являются обязательными,
	* `size`   - кортёж или список из ширины и высоты (по умолчанию - размеры `image`),
	* `crop`   - как и в ATL или ScreenLang, это часть из отрисовываемого изображения: `x, y, xsize, ysize`, по умолчанию `(0.0, 0.0, 1.0, 1.0)`,
	* `anchor` - как и в ATL или ScreenLang, это отступ, по умолчанию `(0, 0)`,
	* `alpha`  - непрозрачность от `0.0` до `1.0`, по умолчанию `1.0`,
	* `rotate` - поворот по часовой стрелке, в градусах, по умолчанию `0`,
	* `zorder` - значение для сортировки по глубине:
		+ Если меньше `0`, то объект будет отрисовываться позади локации (может быть использовано, когда локация имеет прозрачные участки),
		+ Если больше `1e6` (миллион), то будет отрисовываться после изображения `over` локации (может быть использовано для тумана),
		+ В ином случае объект будет отрисовываться после объектов с меньшим `zorder` и до тех, что имеют `zorder` больше
		(у обычных объектов `zorder` обычно равен `y`-координате точки, на которой он стоит).

Используется пользовательский класс rpg-объектов в той же функции, что и обычные rpg-объекты,
но вместо зарегистрированного типа объекта (т. е. строки с именем типа) передаётся ваш класс и
именованные параметры, попадающие в `kwargs` конструктора.

Например:
```
my_obj = add_location_object('location_name', 'place_name', MySuperObject, param1=123, param2=234)
my_obj.your_class_method()
```

Или, если параметров будет много и создавать объект нужно будет не 1 раз:
```
my_obj_params = {
	'param1': 123,
	'param2': 234,
}
my_obj = add_location_object('location_name', 'place_name', MySuperObject, **my_obj_params)
```

***

## Пользовательские функции

Стандартным rpg-объектам можно устанавливать свои функции, которые будут выполняться после стандартной функции обновления перед отрисовкой.  
Пользовательские функции должны принимать объект в качестве аргумента и могут менять некоторые его свойства:  
`x`, `y`, `xanchor`, `yanchor`, `xsize`, `ysize`, `alpha`.  

Примеры:

Плавно удаляем (сначала добавляя прозрачности) 3 уже существующих мячика:
```python
# функция для плавного сокрытия мячика
def ball_hiding(ball):
	dtime = get_game_time() - ball.start_hiding
	hiding_time = 3
	
	ball.alpha = 1 - dtime / hiding_time
	if ball.alpha < 0:
		remove_location_object(ball.location.name, ball, ball.type)

# ...

# получаем список всех мячиков (объектов с типом 'ball')
# в локации location_name, отсортированых по расстоянию до места place_name
balls = get_location_objects('location_name', 'place_name', 'ball')

# для 3 ближайших мячиков
for ball in balls[:3]:
	# запоминаем текущее время и запускаем плавное удаление
	ball.start_hiding = get_game_time()
	ball.user_function = ball_hiding
```

Передвижение для добавляемой машины:
```python
def car_moving(car):
	dist = car.location.xsize
	moving_time = 10
	
	car.x = ((get_game_time() / moving_time) % 1) * dist

car = add_location_object('location_name', 'place_name', 'car')
car.user_function = car_moving
```

***

[Далее ->](./Прочее)  
[<- Назад](./Инвентарь)
