Пятница, 24.01.2025, 11:31
| RSS
F.O.R.U.M.
Главная | Несколько слов о скриптовой модели игры - Форум
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Несколько слов о скриптовой модели игры
frontДата: Вторник, 13.10.2009, 16:30 | Сообщение # 1
Admin
Группа: Администраторы
Сообщений: 152
Репутация: 229
Статус: Оффлайн
Факт первый. Сингловая игра построена на основе мультиплеерного движка. Мультиплеер подразумевает наличие сервера, к которому подключаются клиенты. Все данные (т.е. все объекты игры) существую в первую очередь на сервере, а у клиентов имеются копии этих данных. Естественным образом имеется разграничение обязанностей между клиентом и сервером: сервер отвечает в целом за создание, удаление, хранение объектов, а клиент - за всевозможные _игровые_ манипуляции с ними: отображение, проигрывание анимации и звуков, движение, убиение (но не удаление) и т.п.
Следующий факт. Существует такое понятие онлайн/оффлайн. Что это такое? Дело в том, что загрузить в память все объекты игрового мира сразу невозможно. Для решения этой проблемы конкретно здесь сделаны две вещи:
1. Игра разбита на уровни, и в каждый момент времени загружен только один уровень и, соответственно, загружены только объекты уровня (и давайте не будем обсуждать, как это делают в современных движках). Думаю, с этой идеей всё более или менее ясно.
2. Загружать весь уровень целиком также оказалось накладно. Поэтому в память загружаются только те объекты, которые находятся на некотором разумном расстоянии от игрока. Загрузку объекта называют переходом в онлайн, а выгрузку - переходом в оффлайн. Если конкретнее, то расстояние перехода в онлайн управляется двумя параметрами switch_distance и switch_factor секции alife из файла config\alife.ltx. Их обычные значения:
Код
[alife]
switch_distance = 150
switch_factor = 0.1переход в онлайн произойдёт на расстоянии switch_distance * (1 - switch_factor)
переход в оффлайн произойдёт на расстоянии switch_distance * (1 + switch_factor)
Теперь вспомним про нашу архитектуру. Нетрудно догадаться, что описанный процесс хорошо ложится на эту архитектуру. А именно: загрузка объекта (переход в онлайн) - это создание его клиентской части, а выгрузка (переход в оффлайн) - это удаление клиентского объекта. Серверный при этом остаётся постоянно. Отсюда и второе название серверного и клиентского объектов - оффлайновый и онлайновый соответственно.
Пошли дальше. Скриптовая модель (т.е. вся совокупность доступных классов) отражает эту архитектуру. Есть классы для серверных объектов, есть классы для клиентских. Есть вспомогательные классы общего назначения. Есть и ещё другие, но не будем забегать вперёд.
Пример серверных классов и функций:
- Часть функций объявленных в пространстве имён game и в глобальном пространстве имён (например alife()).
- Крупная иерархия классов, унаследованных от cse_abstract (который сам по себе ещё унаследован от нескольких классов, но в основном все значимые для скриптования серверные классы унаследованы от него)
Пример клиентских классов и функций:
- Все или почти все функции из пространства имён level
- Иерархия классов, порождённых от CGameObject
- Класс game_object (надеюсь, мы ещё разберём этого уродца)
О других пока не будем.
Важно понять, что в сингловой игре это разделение объектов на серверные и клиентские никуда не делось. Есть всё тот же сервер и есть клиент. Клиент разумеется всего один, и сервер - это разумеется этот-же компьютер. Объекты, которые раньше существовали по разные стороны сети, теперь находятся в одном адресном пространстве. Но их взаимодействие осталось прежним: при создании клиентский объект копирует себе нужные ему данные с серверной стороны, при удалении - сохраняет. В процессе жизни клиентского объекта он синхронизируется с серверным, в основном записывая в него свои данные. Используются ли при этом сетевые технологии, или путь передачи данных несколько оптимизирован для сингла - не известно.


 
frontДата: Вторник, 13.10.2009, 16:30 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 152
Репутация: 229
Статус: Оффлайн
Ещё немного лирики.
В голом мультиплее не так уж и много можно делать: бегать за артефактами и палить друг в друга. Совершенно очевидно, что иначе и быть не могло. Синхронизация всех копий клиентских объектов через сервер явно требует приличных затрат. Синхронизировать в совокупности около 30 игроков ещё возможно, но если наполнить уровень хоть вполовину так, как он наполнен в сингле, то явно ничего уже не выйдет.
Глядя на это или по каким иным причинам искусственный интеллект игры исходно создавался в расчёте исключительно на сингл. Вполне может быть, что ваяли его в спешке и просто не продумали архитектурно. Поэтому пресловутый A-Life вышел и не серверным и не клиентским. Он как бы размазан между этими частями. Так что совместное сафари за кабанчиками в мультиплее нам не светит.

К чему я всё это? К тому, что часть классов довольно сложно отнести к серверным или клиентским.

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

Несколько подробнее о клиентских объектах.
Для непосредственного управления клиентскими объектами существует два типа классов:
- классы, унаследованные от CGameObject. С ними есть одна проблема, большинство этих классов обладают весьма бедным интерфейсом и вообще говоря недоступны для программистов. Исключением являются три класса CHelicopter, CCar и hanging_lamp. До всех остальных попросту никак не добраться.
- Класс game_object, который используется для управления всеми онлайновыми игровыми объектами. Убогий уродец, страшный сон архитектора и головная боль скриптёров. Этот класс объединяет в себе все интерфейсы всех объектов, для управления которыми предназначен. В этом чуде около 300 (три сотни) методов! Вызов метода, не соответствующего типу объекта, может быть просто проигнорирован, а скорее всего приведёт к вылету, причём чаще всего без лога. И при этом никак и нигде не документировано, какие же методы относятся к каким типам объектов. Создать этого монстра - это был несомненно дьявольский план, который пришёл в головы творцов игры вероятно по большой укурке.
Что можно делать с game_object? В основном он позволяет получить разную информацию об онлайновом объекте, изменять некоторые его свойства, а также выполнять над объектом разные действия. Например, можно пнуть объект, проиграть анимацию, вылечить, убить (но не воскресить) и т.п.
Это всё хорошо, но помимо изменения свойств довольно часто надо решить следующую задачу: надо выполнить некое действие, когда с объектом происходит что-то конкретное, например объект переходит в онлайн/оффлайн, получил удар/повреждение, взял/выбросил предмет из инвентаря, наконец помер и т.п..

Как раз для этого у game_object есть методы set_callback, set_patrol_extrapolate_callback и set_enemy_callback, которые позволяют решить эту задачу. Но во-первых, некоторые события так не отследить, например переход в онлайн/оффлайн, а во-вторых, независимое использование этих методов не очень-то удобно. Не буду объяснять почему. Знатоки ООП поймут это сразу, а если не верите, попробуйте наладить мало-мальски структурированную обработку событий только этим методом и всё поймёте сами.
Посему эти методы как правило используются в совокупности с классом object_binder, о чём и пойдёт речь в следующей статье. См. следующую часть.


 
  • Страница 1 из 1
  • 1
Поиск:

Для добавления необходима авторизация

Copyright Front Сайт оптимизирован под браузер Opera © 2025