Каждый миг жизни наполнен какими-то событиями. События происходят вокруг нас, они могут происходить, на первый взгляд, сами по себе, а могут быть явным следствием каких-то причин. Однако, как бы не казалось «на первый взгляд», все события имеют какую-либо причину. Даже если вспомнить теорию «Большого взрыва», то можно предположить, что все, что происходит с нами сейчас, есть не что иное, как следствие этой самой «первопричины». Существует такая умозрительная теория, что если знать состояние всех частиц в какой-то момент времени, то можно предсказывать будущее ...
Итак, что, исходя из этого, можно придумать применительно к нашей задаче, а именно, к написанию игр?
Сделаем предположение, что всю игровую ситуацию можно описать как набор неких событий, многие из которых уже произошли, а возможно - еще только собираются произойти. Также сделаем предположение, что в нашей игре все возможные основные события уже заложены в память компьютера, так что будет несложно прийти к выводу, что в игре все события наступают вследствие «наступления» неких «родительских» событий. И всю игровую логику можно представить именно в этих терминах. Вообще текущее положение дел в игре можно условно разделить на две части - низкоуровневую, куда будут входить, скажем, положения спрайтов на экране, текущие настройки пользовательского интерфейса, характеристики персонажей, и высокоуровневую, то есть, общее логическое состояние сюжетной линии игры, по которой можно сказать, где игрок находится в данный момент - в середине игры, или же в ее начале, в самом конце ее или же еще только осваивается с первыми игровыми заданиями.
Вот тут мы подошли к одному из ключевых понятий, к «квесту». Что это такое? Это одновременно и жанр игры типа «приключение», и понятие помельче, означающее некое игровое задание, например, принести из Очень Темного Леса Очень Сладкое яблочко игровому персонажу. При написании игры этого жанра необходимо решать непростую задачу - каким-то образом учитывать исполнение заданий и выдача очередных поручений на основании уже решенных головоломок. Для этого и можно воспользоваться понятием «событие».
Каждый раз, когда игрок делает что-либо, происходит череда событий. Вот он нажал на клавишу - событие. Вот он убил страшного монстра - событие. Вот пошевелил мышью - тоже событие! Так какие же из них нам надо учитывать? Будь у нас Абсолютный Суперкомпьютер, способный заменить Реальность, мы бы на каждый квант времени «повесили» бы ярлык «событие» и со скоростью света обрабатывали бы все их, получив результате еще одну, вполне реальную Вселенную. Однако у нас всего лишь жалкий третий Пентиум! Очевидно, что нас не интересуют мелочи! Мы собрались писать игру, а это значит, что мы умеем выделять главное и не обращать внимания на частности (или должны уметь ...). Поэтому под событием будем понимать нечто значительное, например, выполнение квеста.
Для того чтобы работать в подобном, событийном мире, надо иметь возможность оперировать некими объектами, как и в любой подобной ситуации. Само собой напрашивается решение - объекты будут являться событиями. То есть, это некие control-ы, или, попросту - «контролы».
Для этого введем класс объектов, которые содержат в себе два основных метода - int control_activate() и int control_run(). Идея состоит в том, чтобы контрол мог «сработать» в определенной ситуации, то есть выполнить функцию control_run(). Для того чтобы контрол выполнил эту функцию, необходим "положительный" ответ от функции control_activate(). Функция control_activate() содержит в себе логическое выражение от некоего набора контролов, каждый из которых может возвращать количество срабатываний . А функция control_run() в ответ увеличит на 1 счетчик собственных срабатываний и выполнит какие-либо действия, предусмотренные сюжетом.
Пример:
Надо выполнить квест - убить хотя бы десять монстров в лесу, тогда старейшина деревни даст амулет.
// Простейший контрол №0, отвечающий за событие «убийство монстра» // Просто увеличивается счетчик срабатываний контрола int control_activate0000() { return TRUE; } int control_run0000() { return TRUE; } // - контрол №1, отвечающий за получение амулета, // на основании контрола №0 int control_activate0001() { if( Control(0) >= 10) return TRUE; // - если убито десять или более // монстров, вернуть ИСТИНУ. return FALSE; } int control_run0001() { Say("Молодец, ты справился с заданием!"); // - окно с фразой GiveItToPlayer(ARTEFACT_AMYLET); //- дать амулет игроку return TRUE; }
Как видно, для каждого контрола надо писать отдельные функции. Их лучше всего исполнить в виде скрипт-модулей, благо на сегодняшний день в интернете есть множество бесплатных и свободно распространяемых скрипт-интерпретаторов. Генерировать функции контролов лучше всего автоматически в редакторе локации, разве что потом дополнять их вручную.
С помощью контролов можно решать самые разные задачи - от выполнения квестов до управления всевозможными триггерами/ловушками, дверьми и т.д., все, работу чего можно рассматривать как событие.
Жанровая принадлежность игры тут не играет ообой роли, так как выполнение заданий есть в любом жанре - в квестах, аркадах, РПГ, 3D-action ...
2000-12-25
Фролов Андрей ака FAL.