Я вообще вот чего думаю. Когда я начал мечтать _свою_ игру - RPG (естественно, что это должен был быть "живой" мир). То начал это делать, когда в моем тогдашнем пацаненском мозгу (это давно началось) сверкнула мысль о том, что совсем-совсем не обязательно все время все для всех считать. Я думал о вышеподобных формулах, но так как у меня к ним выработался стойкий страх после школьной математики (ну боюсь я ее %) и из-за этого всего, кстати, в ВУЗ никак не поступлю, вот такая вот досада), я решил это дело отклонить и подумать немного просче. Я как-то писал уже большой-прибольшой файл по этому поводу, но он затерялся. Вкратце же это выглядит так:
Есть мирок небольшой, допустим с планетку. На нем у нас есть живые объекты, которые проявляют свою активность, что-то делают, что влечет за собой всяческие изменения... Есть предметы, которые тоже что-то делают, но, как правило, только в небольшой области (не считая всяких глобальных артефактов оф биг бум и прочего). Существа разумные (так я их называю, ибо не тока люди разумные насыщают мир, но и люде неразумные и разумные не люди и т.д. и т.п.
) бывают очень активными - это всяческие герои, не очень - торговцы, путешественники и совсем не очень - это, например, крестьяне, которые кроме "утро - поле, вечер - таверна, ночь - домой" ничего особо и не умеють... Далее прога распределяет приоритеты для последующего расчета всех этих пиплов и не очень... Нет. Сначала скажу о том, что мир состоит из псевдо локаций, т.е. визуально - весь мир - одно целое, а внутри - это много отдельных локаций. Так вот, расчитывать нам нужно лишь то, что нам нужно. Это же так очевидно. :-] Ну а на деле это обозначает то, что _тщательно_ мы расчитываем лишь то, что находится в нашей и примыкающих к ней локациях. Всех крестьян, бабок и деток, аборигенов то бишь, мы считаем только тогда, когда находимся рядом с ними. Героев же, странствующих торговцев и путещественников, которым не сидится на месте, нам придется считать всегда, хотя и их можно считать не всегда, а только тогда, когда они "идут на дело", если же они сидят на месте или просто перемещаются из одной точки в другую, то нам можно делать прогнозы заранее (евстевственно подразумевается, что игроку это не видно и незаметно, атмосферу нужно сохранять всеми силами, иначе никакой GeForce не спасет), т.е. перед тем как посчитать то, что нашему перцу нужно идти на север за Медведями, точнее перед тем как ему туда попасть, записываем ему в "судьбу": "нечаянно" найти заныканого ранее монстрика редкого. В "судьбе" же "монстрика редкого" также будет записано, что ему просто необходимо найтись для нашего перца. Необходимость также будет ограничена разумными пределами, дабы не было ситуаций, когда монстер бакланит какого-нибудь не вовремя нарисовавшегося мага, а тут ему судьба говорит: "забей и дуй туда-то". Это не верно. "Судьба" (так я называю навязываемую тактику поведения) - это нечто напоминающее своей природой магнит. Она не жестко указывается, она "передумывает" в зависимости от ситуации. Т.е. вот хотелось нам встречу сделать немного монстяры с героем, но маг проявился: "Ну что ж..." - сказал судьба и выкинула кубик "быть или не быть" для следующего события (именно события, не препятствия - игра не должна быть агрессивной). Из этого следует, что каждый объект у нас имеет флажок занят/не занят (флажок не жесткий, а гранулированный... ...не, не гранулированный, а-а, гравированный... не, не гравированный, во! Точно! Градуированный. ... Хотя все-равно сюда мало подходит
Вобщем, приоритеты и между ними будут - одна работа - одного количество очков, другая работа - соответственно и другое количество очков... У кого больше тот и вадит
, главнее то бишь). Вот.
Ну и возвращаясь к теме локаций и разных живых существ коснусь темы хранения данных этими живыми и неживыми объектами (это тоже одна и тех простецких идей, которые могут сослужиьт весьма не плохую службу). Скажу честно - мой вдохновитель в этом направлении - игра Elite + некоторые довесы с моей стороны.
Данные в каждом объекте динамичны. Все основано на переменных, которые могут всячески изменяться, т.е. удаляться, добавлять, изменяться. На деле это выглядить примерно так (самый простой случай):
Есть функция, которая возвращает нам, скажем, возраст. Function GetObjectAge:Integer... А, у вас же Си, ну тогда int getObjectAge() (это я козыряю пальцами по типу "мине усе известно, мине море ни почем").
Так вот, эта самая функция делает так:
Смотрит, есть ли такая переменная как Age в блоке данных объекта.
Если есть, она возвращает просто-напросто ее значение, если же нет, то:
Создаем таблицу _неизмененных_ данных для данного объекта от числа, которое (уже неумираемо) хранится у каждого объекта. Но и это число тоже может расчитываться рандомной формулой от скажем числа группы. Рандом тут используется "фиксированный", как я это сейчас называю.
Т.е. от одного какого-либо числа все время будет выпадать другое, но все время то же самое число. Для тех кто рядом с танком: если у нас цифирь "1", то рандом от нее будет _всегда_ выдавать, например, "345", а если цифирь равна "345", то рандом от нее будет "137".
Идея состоит в том, что зная одно число мы всегда сможем от него _точно_ узнать другие. При этом, если значение не изменялось - нам не надо хранить эту переменную. Неудобство лишь в том, что если мы хотим сделать что-то свое. Скажем, чтобы у нас была на карте деревня (карта по такому же рандомному принципу рисуется) именно такая, какую мы хотим видеть - нам нужно будет отработать каждую переменную, которую мы не хотим оставлять без внимания, а это занимает место... Но, вобщем-то это не есть большой минус, без этого пока никак. Ну вот.
Далее, после того, как мы создали таблицу параметров, которые у нас положены для текущего объекта, мы проверяем заведенные у данного объекта переменные и если находим ту же, которая указывается у нас в параметрах, то изменяем значение, присвоенное по умолчанию (т.е. сгенерированное от индивидуального числа) на то, которое когда-то кем-то выставлялось... Может чего и пропустил, но в общем так...
Теперь касательно того, как же я собираюсь сохранить целостность мира, если не собираюсь просчитывать его все время... Все, как всегда, просто. =) Перед тем как "выключить" тот или иной объект из списка обрабатываемых в реальном времени, мы записываем ему "дату последнего посещения" (это у меня от чата проклюнулось %) ). А потом, когда он попадает в "зону включения", смотрим у него дату и делаем процедуру "Хэ". Процедура "Xэ" расчитывает все то время, которое он спал в ускоренном режиме специальными и не очень алгоритмами. А эти самые алгоритмы - это совсем другая история, ибо они часто индивидуальны и требуют переключения хода мышления, а то будет некрасиво. Об этом потом, если захотите. Замечу лишь то, что для того, чтобы наш объект не "спал" все то время, пока мы далеко от него - вводим такую штуку, как "будильник" (дебильник %] ), т.е. перед тем, как "выключить" объект - мы ставим ему дату следующего просыпания. Само просыпание может быть разного вида: полным и не очень. Полное, это когда он попадает в список реально активных объектов, а "не очень" - это когда он проснулся, куда-нибудь рыпнулся и опять заснул. Так же кину мысль про то, что "будить" часто придется всю локацию, чтобы реально все посчитать. И замечу, что ... Щи-и-ит! Обидно. Так обломить! Отвлекли на минуту и все, мысль ушла вместе с народом. Екарный бабай! А так все шло... Это от того, что я сейчас на работе. %) Ладно, потому вспомню в лучшей форме, а может где в тетрадях найду, если раньше про это думал... Все-равно жалко... Что-то мелкое, но довольно важное на кончиках палцев крутилось... Дальше... Периодически (можно выбирать моменты, когда у нас идет мало расчетов) можно будить все места (по очереди и не очень, в зависимости от ситуации) для того, чтобы потом не пришлось слишком долго все расчитывать для какой-либо компом забытой локации, ведь чем древнее у нас дата последнего посещения, тем больше считать - это очевидно. Еще вот свежая мысль пришла о том, что и здесь перед "выключением" объекта можно намечать "план", по которому он будет считаться потом, чтобы было быстре... Хотя нет. Пусть это будет потом, потому что "потом" свежее. А потери невелики: просто с планом можно было бы редко его "побуживать" и кое-что делать. Хотя на деле не проверено - скорее всего тут даже потерь больше: мелочь все время отъест. Вот вроде.
Теперь предметы, но с ними так же как и с объектами только проще. Приведу пример с бутылкой (где-то я уже говорил про это...): собрали мы всяких фруктов и запихали их все в бутыль, поставили и забыли, записав объекту, что поставили его со свежими фруктами такого-то числа мирового времени. После, мы видим этот объект только как обертку с неизвестным внутри. Как только дело доходит до реального действия (начали рассматривать как следует или применять по-разному), то делаем расчет по принципу (думает комп сам с собою):
- Ага, фрукты у нас от этого числа, ясно... так у них срок годности того уже...
- Да ты че?
- Ну да, говорю, пропали. На списание...
- Да ну, скиснули они лучше.
- Да, точно! Скиснули...
- Та-а-ак, с этим понятно. А бутылка?
- Что "бутылка"?
- Ну это, она из чего?
- Из стекла.
- Эх, ладно. Была б из глины какой-нить неправильной, то мы бы ее кислым вином проели. Вот клево было б!
- Да, клева, тока не вшло. Пусть вино будет.
- Ладно, пусть будет, игрокам ненасытным на утехи...
- Ага...
Вот. Примерно ясно, думаю...
Ну и глядя с точки зрения sailor, признаю, что моя мысль не заменит изначальной идеи (от том, чтобы каждый объект имел сугубо личный блок данных) вцелом, но поможет что-то заоптимизить... Кроме того, я не обижусь, если она не пригодится и гордо заявляю, что сам не прекращаю ее дорабатывать и совершенствовать, и хотя я и не планирую именно графического движка (я вообще любитель ADOM'а и roguelike игр, хотя реально играл только в ADOM %) ), но в тексте я ее сделаю - это точно. А вообще в дневнике в своем (веду дневник с рабочим названием "Жизнь чела в период написания игры его мечты"
) я уже выложил идею о том, что мир не будет привязан к оболочке визуально отображающей его. Если кратко, то: мир дает клиенту (да, это мультиплеерная фиговина планируется) лишь описание мира и, возможно, описание того, как рисовать тот или иной объект... А клиент может быть и текстовым и графическим. Если поподробнее, то все хранится в самом сложном варианте: все вплоть до описания того, как у нас выглядят листья на дереве, но если клиент текстовый (аля измененный MUD (без разбиения на клетки)), то выдаем ему словесное описание: тут стоит дерево, тут дом, посмотрел на дерево - рассказали про дерево. Кстати, этот клиент даже, наверное, более требователен, ибо ему к лицу слать все в художественном описании, пусть и компьютеризированном (из чего следует, что описание часто будет повторяться); если же клиент псевдографический (аля ADOM (Ancient Domains Of Mystery)), кстати, именно на него был изначальный расчет, то все данные можно пересылать в упрощенной форме. Этому также способствует и то, что мир в таком представлении так или иначе поделен на клетки (буквы-то одно размера
). Ну а для графики идет полное описание, которое, в принципе-то сводится к передачи одного числа и, возможно в будущем - алгоритма, по которому от этого числа строится объект. ...Пока ходил за булочкой (по улице) - сильно обратил внимание на всякие облачка там, деревья... эх, красота - графика нужна адназначна... ...но позже...
Кстати, мысль о том чтобы мысли на мыло писать кажется мне несколько жадной. :|
Больше высказываешь - больше в голову приходит новых мыслей - это доказанный факт. И вообще, это у буржуив приятно торговать голыми идеями. %] Я вот, например, пока все это писал еще кое-чего додумал и немного придумал, сформируются мысли получше - расскажу еще.
И еще, предупреждая вопрос "А это что за покемон?", скажу, что пассворд от форума пока до меня не дошел (ну никак до меня не доходит... все эти цифирьки и буковки... %) ), потому я пока делаю вид, что в гостях...
...Фуф, хотя бы крато, но я выложил направление своих мыслей. %)
P.S. Запишу-ка я это в дневник...
P.P.S. Чувствую, что кое-где я уже заговариваюсь, поэтому уже ожидаю вопросы на мыло и сюда...
P.P.P.S. Прошу просчения за обшибки. Я уж не стал проверять - некада уже.
Данила aka MoonStone.