RU

Текстовые РПГ!

Ajenta Moderator 20.02.2014 15:52 205 comments 96314 views

Начинаю эту тему, ибо надоело по частям всё собирать откуда-то.
Предлагаю здесь обсуждать всю механику, тактику, кодинг и тому подобные вещи.
Как и что делать чтобы было хорошо.

За одно тут же варианты сражений, прокачки, параметров… всё, о монстре под названием “текстовая рпг”.

Делимся кодом, наработками, сюжетами!

Aleks Versus, согласен. Игрок надо подать то, что будет ему интересно. Для меня, допустим, важно разнообразие. Этим очень выделяются ККИ, где много карт и вариаций с их игрой. Поэтому я так же застопорился на том, чтобы придумать саму систему с позиции интересности для игрока.

Aleks Versus, посмотрел два движка. Как по мне тринити больше подходит для боев в реальном времени. Идея Casralis’а интересна, но с первого просчитывания тоже не всё усвоил сразу усвоил) Прочитал пару интересных статей о системах боя в РПГ, в которых разработчики выделяют критерии хорошей игры.

В раздумьях на своим боевым движком выделил то, что хотелось бы видеть:
1) Не должно быть чёткого разделения на классы персонажа. Я представляю схему развития как разветвленное дерево, в котором игрок выбирает по какому именно ему пути идти. В этом дереве определенная способность будет стоит какое-то количество баллов опыта, которые игрок получает за задания, в боях или ещё каким-либо способом. Игрок сможет попробовать создать многогранного специалиста, но с малым навыком в умениях, либо же углубиться в одну или две, получив при этом бонус от глубокого изучения.
2) Хотелось бы видеть в партии 5-6 персонажей, которые будут отличаться стилем боя. Прикрытие более слабых, допустим тех же магов и стрелков, воинами и существами рукопашного боя. Согласитесь, волшебник же никогда не начнет бой впритык с целью. Если не организовывать прикрытие, то противник при правильном алгоритме действий будет атаковать хиленьких персонажей.
3) С позиции боевой системы мне больше понравилась ККИ Берсерк. От туда интересно было бы взять влияние местности и полёт существ.
4) Конечно, хотелось бы добиться простоты и разнообразия одновременно. В ККИ это достигается количеством карт, а в РПГ классами. Под концепцию моего игрового мира не подходит ККИ, поэтому я придумываю древо развития)

Storm:

Aleks Versus, посмотрел два движка. Как по мне тринити больше подходит для боев в реальном времени. Идея Casralis’а интересна, но с первого просчитывания тоже не всё усвоил сразу усвоил) Прочитал пару интересных статей о системах боя в РПГ, в которых разработчики выделяют критерии хорошей игры.

В раздумьях на своим боевым движком выделил то, что хотелось бы видеть:
1) Не должно быть чёткого разделения на классы персонажа. Я представляю схему развития как разветвленное дерево, в котором игрок выбирает по какому именно ему пути идти. В этом дереве определенная способность будет стоит какое-то количество баллов опыта, которые игрок получает за задания, в боях или ещё каким-либо способом. Игрок сможет попробовать создать многогранного специалиста, но с малым навыком в умениях, либо же углубиться в одну или две, получив при этом бонус от глубокого изучения.
2) Хотелось бы видеть в партии 5-6 персонажей, которые будут отличаться стилем боя. Прикрытие более слабых, допустим тех же магов и стрелков, воинами и существами рукопашного боя. Согласитесь, волшебник же никогда не начнет бой впритык с целью. Если не организовывать прикрытие, то противник при правильном алгоритме действий будет атаковать хиленьких персонажей.
3) С позиции боевой системы мне больше понравилась ККИ Берсерк. От туда интересно было бы взять влияние местности и полёт существ.
4) Конечно, хотелось бы добиться простоты и разнообразия одновременно. В ККИ это достигается количеством карт, а в РПГ классами. Под концепцию моего игрового мира не подходит ККИ, поэтому я придумываю древо развития)

Могу немного рассказать про то, как я пытался реализовать “геройную” систему боя, но для одного персонажа на c# в visual studio.
У нас есть переменная id для обозначения номера клетки персонажа. При нажатии на одну из клеток идет проверка переменной id персонажа с id соседних клеток, т.е. проверка может ли игрок попасть туда. И если может, то Label1.Text= “Игрок”; ( Не знаю как сделать это в qsp). Там же проводится проверка на наличие противника в клетке, если есть то наш код атаки, если нет - перемещения.

SneakBug8, ну как реализовать бой по типу Героев я представляю, только в квадратных клетках с координатами x и y. Хотя лично я люблю гексовую сетку, но пока не сильно представляю как её реализовать математически в коде. Но если вводить клеточное поле для боя, то придется прописывать алгоритм передвижения для врагов, допустим тот же A*, в котором я пытался разобраться. В принципе, не сложно, но я не ставлю пока перед собой задачи создание именно такого типа боя)

Если ты планируешь просто ряд своих и ряд чужих и по очереди пуляться, то никаких проблем, но никаких прикрытий не будет. Тут я привел код на 1 персонажа, а ты сделай его на 6 (легко делается) и только остались алгоритмы монстров, на которые посмотреть можно в тех же героях III.

SneakBug8, я представляю это несколько иначе. Первый ряд у игрока это прикрытие своих стрелков, магов и всевозможных хрупких персонажей, проще говоря это бронированные воины. За ними идет ряд стрелков и магов. Есть отдельно колонка для летающих персонажей. Так же и у противника. Чтобы пробиться к стрелкам, нужно вначале убрать воинов.

Storm:

SneakBug8, я представляю это несколько иначе. Первый ряд у игрока это прикрытие своих стрелков, магов и всевозможных хрупких персонажей, проще говоря это бронированные воины. За ними идет ряд стрелков и магов. Есть отдельно колонка для летающих персонажей. Так же и у противника. Чтобы пробиться к стрелкам, нужно вначале убрать воинов.

Тогда единственная сложность это при нанесении урона стрелкам это проверить наличие воинов.

SneakBug8, просто не вижу причин делать бой в клеточках) Может кому-то было бы и интересно, но не мне)

Aleks Versus Moderator 23.05.2015 14:33 (10 years ago)

Storm,
идея Casralis’а столь же проста, сколь и запутана при описании. Поэтому врубиться в неё, прочитав описание Casralis’а, довольно сложно. Но если будет интересно, я объясню суть.

Storm:

В раздумьях на своим боевым движком выделил то, что хотелось бы видеть:

Под концепцию моего игрового мира не подходит ККИ, поэтому я придумываю древо развития)

Да, пришёл к тем же самым выводам. Расскажу и я про свои раздумья над системой боя.
Сначала я не особо парился и делал систему боя 1х1.

Что должно было разнообразить сражения:
1. Классы, типы, подтипы, подвиды вооружения. Я начал писать базу оружия для давно задуманной рпг, где были мечи, топоры, молоты, ножи, кинжалы, луки, арбалеты, огнестрельное оружие, разные виды зачарования, модернизации и проч.
2. Восприимчивость врагов и гг. Практически каждая атака сочетает в себе несколько типов урона. Например, огненный меч наносит эм… рубящий и огненный урон. Против огненного элементаля огонь бесполезен, а значит элементалю прописывалось свойство неуязвимости к огню и уязвимость к воде, например, и т.д. Т.о. я пришёл к созданию базы монстров, против которых нужно было подбирать наиболее эффективное оружие.
3. Из разнообразия вооружения (в частности из-за основной разницы между стрелковым и оружием ближнего боя) пришло описание местности. Одним из ресурсов стало расстояние. Однако это завело меня в тупик, поскольку ни герой, ни враг не могут отходить друг от друга на сколь угодно большое расстояние, а значит размер “комнаты” пришлось бы ограничивать. Это даёт нам местность, где невыгодно использовать допустим динамит, или стрелковое оружие.
4. Влияние местности. По-моему, я тоже свистнул это из какой-то игры, но не помню из какой. Основными влияниями стало: молчание (нельзя читать заклинания), паралич (нельзя передвигаться во время боя), бессилие (можно передвигаться и читать заклинания, но нельзя использовать оружие). Потом появились другие типы местности и влияний.

Всё это было очень весело и технически реализуемо, но сначала trinity масетрсета, а потом и неоконченная работа над TTSWD зажгли во мне желание написать боёвку, в которой нужно не только правильно подбирать оружие с учётом местности и влияния на врага, но и приходилось “решать проблему на месте”. “Пазл”, как это называет Аджента. В trinity и ttswd есть то, чего нет в простой боёвке типа “удар-ответка”, а именно: ты видишь, что готовит тебе противник, и можешь подготовиться к его действию, если у тебя есть необходимые ресурсы. Это именно тактические бои, в отличие от предлагаемой “сетки” как в героях, кингсбаунти и пр. Стратегия это конечно интересно, но в рамках текстовой игры выглядит неуместно, громоздко и аляповато. Поэтому-то, когда меня осенила идея сделать двумерную(трёхмерную) комнату для боёвки, я постарался поскорее забыть эту идею, или хотя бы свести бой в такой комнате к минимуму, чтобы игрок не отвлекался от сюжетной части, пропадая в бесконечных долгих боях.

Короче, я до сих пор думаю, как всё вышеперечисленное сублимировать.
Всякие примочки типа отравлений и накладываемых эффектов тоже могли бы разнообразить бой, но это уж так - плюшки на десерт.

Aleks Versus Moderator 23.05.2015 15:08 (10 years ago)

Storm:

Хотя лично я люблю гексовую сетку, но пока не сильно представляю как её реализовать математически в коде.

Это, кстати, не сложно. Гексы тоже лежат в двух измерениях.

Aleks Versus, к классам, типам урона, восприимчивости врагов, разнообразию вооружения пришел и я. В принципе у меня уже сформировалась идея боевой системы, осталось только реализовать в её в коде.
Посмотрел я боевой движок TRINITY. К самому движку притензий не имею. Но лично мне не нравиться то, что мы в начале игры загружаем в память информацию о всех монстрах и оружии. Я считаю это не очень хорошей идеей, особенно когда монстров и предметов очень много. В памяти будет держаться переменные, которые не будут использоваться. У меня для каждого предмета своя локация, и когда игрок экипирует предмет он обращается к этой локации, берет от туда значения и добавляет их в свои характеристики.
На счет гексовой сетки: я тоже натыкался на подобный пример. Проблема в том, что нам всё равно придется выводить её на плоское пространство, которое имеет две координаты, а значить нам нужны координаты центра гекса. А они получаются дробные, а в QSP только целые числа :) Видел вариант когда используются три оси координат на плоскости, но пока не сильно разобрался в том примере. Но так или иначе, нам всё равно придется выводить видимый для игрока объект на 2D плоскость, а значить должен быть алгоритм перевода координат из трех осей в две.
Сейчас застрял на системе создания собственных вещей. Я понимаю, что это должен быть массив. В моей системе экипировки когда одевается предмет значения берутся из локации предмета. Но и в этой системе есть свои недочеты. У меня сложилась интересная задачка: допустим у нас есть два предмета с названием “Меч”, у одного показатель урона 5, у второго 8. Вопрос: как сделать так, чтобы программа понимала какой “Меч” мы хотим экипировать? У меня это в голове пока не укладывается)
В играх натыкался на две системы создания предметов. Первая самая распространенная, работает по принципу “принеси мне то-то и то-то, а я дам тебе это” :) В коде реализуется очень просто, но чтобы заинтересовать игрока должна иметь большое разнообразие создаваемых предметов. Вторая более сложная: игрок сам выбирает параметры предмета, который создаёт. Допустим, у нас формируется массив значений отвечающих за этот предмет. Снова рождается задачка: как его вызывать, если в игре уже присутствует предмет с таким же названием?)
Но это так, лишь мои размышления :)

Aleks Versus Moderator 25.05.2015 11:02 (10 years ago)

Storm:

Я считаю это не очень хорошей идеей, особенно когда монстров и предметов очень много.

Ха-ха. Мы с тобой прям одинаково мыслим.
Я тоже сначала писал для каждого предмета отдельную локацию, но потом понял, что и это слишком громоздко и излишне. Поэтому-то я и перешёл на базы - локации, на которых собраны оружие, монстры и пр. В нужный момент происходит обращение к базе, из которой уже берётся всё необходимое и прописывается в переменные. Пример:

Spoiler
#base.obj
! получение предмета из базы
$args[0] = $args[0]	&	!	краткое имя предмета/идентификатор вида
$args[1] = $args[1]	&	!	дополнительные параметры предмета
$args['obj']+="<obj> "	&	!	идентификатор класса
:ночное_видение
if $args[0]='ночное_видение':
	$args['obj'] += '[:ночное_видение:] [name:Инфракрасные очки «Ночное зрение»|Инфракрасных очков «Ночное зрение»|Инфракрасным очкам «Ночное зрение»|Инфракрасные очки «Ночное зрение»|Инфракрасными очками «Ночное зрение»|Инфракрасных очках «Ночное зрение»:name] [np:[доспех] [очки] [инфракрасное зрение]:np] [text:Они позволяют видеть в темноте.:text]'
end
:зажигалка
if $args[0]='зажигалка':
	$args['obj'] += '[:зажигалка:] [name:Зажигалка|Зажигалки|Зажигалке|Зажигалку|Зажигалкой|Зажигалке:name] [np::np] [text:Пригодится для разведения огня.:text]'
end
:питательная_паста
if $args[0]='питательная_паста':
	$args['obj'] += '[:питательная_паста:] [name:Тюбик питательной пасты|Тюбика питательной пасты|Тюбику питательной пасты|Тюбик питательной пасты|Тюбиком питательной пасты|Тюбике питательной пасты:name] [np:[еда]:np] [text:Питательная паста, которая в любой момент восстановит ваши силы до первоначального уровня.:text][eating:'+"if power['now']<power['start']: power['now']=power['start'] & $print[]='<font color=#000044>Вы съели порцию питательной пасты. Она полностью восстановила ваши силы.</font>' else $print[]='<font color=#000044>Вы съели порцию питательной пасты.</font>'"+':eating]'
end
:протонная_граната
! прибавить 60 к параграфу
if $args[0]='протонная_граната':
	$args['obj'] += '[:протонная_граната:] [name:Протонная граната|Протонной гранаты|Протонной гранате|Протонную гранату|Протонной гранатой|Протонной гранате:name] [np:[снаряд] [используемый]:np] [useon:60]  [text:Сильное оружие. Следует помнить: не во всякой ситуации ее можно использовать. Надо, чтобы рядом было какое-нибудь укрытие.:text]'
end
:свеча
if $args[0]='свеча':
	$args['obj'] += '[:свеча:] [name:Свеча|Свечи|Свече|Свечу|Свечой|Свече:name] [np::np] [text:Длинный огарок свечи.:text]'
end
:антигравитатор
! прибавить 80
if $args[0]='антигравитатор':
	$args['obj'] += '[:антигравитатор:] [name:Антигравитатор|Антигравитатора|Антигравитатору|Антигравитатор|Антигравитатором|Антигравитаторе:name] [np:[доспех] [одежда] [пояс] [используемый]:np] [useon:80]  [text:Металлический пояс-антигравитатор. Судя по миганию зелёного индикатора на пряжке – нуждается в подзарядке. Впрочем, если в этом действительно появится необходимость, можно пролететь некоторое расстояние.:text] [pos:пояс:pos]'
end
:рог
! прибавить 96 к номеру параграфа
if $args[0]='рог':
	$args['obj'] += '[:рог:] [name:Обломок рога|Обломка рога|Обломку рога|Обломок рога|Обломком рога|Обломке рога:name] [np:[используемый]:np] [useon:96] [text:Тяжелый черный крюк, очень прочный, гладкий, на изломе шероховатый.:text]'
end
:подводная_маска
! вычесть 40 из параграфа
if $args[0]='подводная_маска':
	$args['obj'] += '[:подводная_маска:] [name:Подводная маска|Подводной маски|Подводной маске|Подводную маску|Подводной маской|Подводной маске:name] [np:[используемый]:np] [useon:-40] [text:Маска для подводного плавания с трубкой, к которой прикреплен баллончик сжатого воздуха. Воздуха в ней не много – хватит минут на пятнадцать.:text]'
end
:кошель
if $args[0]='кошель':
	$args['obj'] += "[:кошель:] [name:Карман|Кармана|Карману|Карман|Карманом|Кармане:name] [np::np] [text::text] [pos:пояс-кошель:pos]"
end
:короны_розы
if $args[0]='короны_розы':
	$args['obj'] += '[:короны_розы:] [name:Большие серебряные монеты с изображением короны и розы|Больших серебряных монет с изображением короны и розы|Большим серебряным монетам с изображением короны и розы|Большие серебряные монеты с изображением короны и розы|Большими серебряными монетами с изображением короны и розы|Больших серебряных монетах с изображением короны и розы:name] [np:[монета]:np] [text::text]'
end
:бант_оранжевый
if $args[0]='бант_оранжевый':
	$args['obj'] += '[:бант_оранжевый:] [name:Оранжевая лента|Оранжевой ленты|Оранжевой ленте|Оранжевую ленту|Оранжевой лентой|Оранжевой ленте:name] [np:[монета]:np] [text::text]'
end
:фляга
if $args[0]='фляга':
	$args['obj'] += "[:фляга:] [name:Фляга|Фляги|Фляге|Флягу|Флягой|Фляге:name] [np:[фляга] [напиток]:np] [maxchrg:2][text:<DIN1:gosub 'get.daughter.obj','ПОЯС-ФЛЯГА'
if $temp_id[0]='ФЛЯГА_000013':
	$args[111]='Изобретённое стрекозой приспособление для транспортировки жидкости. Сухой плод, похожий на небольшую бутылочку, обвязанный лианой.'
elseif $temp_id[0]='ФЛЯГА_000016':
	$args[111]='Покрытый узорами сосудик на серебрянной цепочке. Здесь когда-то хранились духи, теперь вы используете его как фляжку. '
end
args[22]=charge_array[arrpos('$id_array',$temp_id[0])]
$args[111]+=' '+$func('get.word.end',args[22],'Осталось на '+str(args[22])+' глоток.|Осталось на '+str(args[22])+' глотка.|Осталось на '+str(args[22])+' глотков.|Фляжка пуста.')
$result=$args[111]
killvar '$temp_id':1DIN> Каждый глоток восстанавливает 2 единицы СИЛЫ.:text] [eating:args[9]=2
$print[]='<font color=#000044>Вы сделали глоток.</font>'
if power['now']+args[9]<=power['start']:
	power['now']+=args[9]
	$print[]='<font color=#000044>СИЛА увеличилась на '+str(args[9])+'.</font>'
elseif power['start']-power['now']<args[9] and power['start']-power['now']!0:
	args[8]=power['start']-power['now']
	power['now']=power['start']
	$print[]='<font color=#000044>СИЛА увеличилась на '+str(args[8])+'.</font>'
else
	$print[]='<font color=#000044>Но он потрачен зря. Ваша СИЛА и так уже достигла максимального уровня.</font>'
end
:eating][pos:пояс-фляга:pos]"
end
:шкура
if $args[0]='шкура':
	$args['obj'] += '[:шкура:] [name:Шкура|Шкуры|Шкуре|Шкуру|Шкурой|Шкуре:name] [np::np] [text:Красивая переливчатая мягкая шкура.:text]'
end
:смола
if $args[0]='смола':
	$args['obj'] += '[:смола:] [name:Смола|Смолы|Смоле|Смолу|Смолой|Смоле:name] [np::np] [text:Тонкая, коричневая, на ощупь напоминающая мягкую пластмассу, лента источает восхитительный запах. Это потёки ароматической смолы, год за годом сочившейся из ветвей и застывавшей на воздухе. Ученые из Лаборатории Мерфи собираются предложить ее парфюмерной промышленности.:text]'
end
:плюмаж
if $args[0]='плюмаж':
	$args['obj'] += '[:плюмаж:] [name:Плюмаж|Плюмажа|Плюмажу|Плюмаж|Плюмажем|Плюмаже:name] [np::np] [text:Тёмно-красная оторочка из перьев.:text]'
end
:плод
! вычесть 176
if $args[0]='плод':
	$args['obj'] += '[:плод:] [name:Плод|Плода|Плоду|Плод|Плодом|Плоде:name] [np:[используемый]:np] [useon:-176] [text:Чёрный шар размером с яблоко. Он так твёрд, что нож не оставляет на нём и царапины.:text]'
end
:меорвин
if $args[0]='меорвин':
	$args['obj'] += '[:меорвин:] [name:Меорвин|Меорвина|Меорвину|Меорвин|Меорвином|Меорвине:name] [np:[еда]:np] [text:Меорвин. Тонкая пластиковая трубочка с зеленым шариком внутри. Сильнейший тонизатор... и реакцию улучшает. Одного такого шарика хватит на две недели... Если проглотите шарик, ваша ЛОВКОСТЬ увеличится на 1.:text] [eating:fast["now"]+=1 & $print[]="<font color=#000044><i>ЛОВКОСТЬ увеличилась на 1</i></font>":eating]'
end
:огнетушитель
! вычесть 100
if $args[0]='огнетушитель':
	$args['obj'] += '[:огнетушитель:] [name:Огнетушитель|Огнетушителя|Огнетушителю|Огнетушитель|Огнетушителем|Огнетушителе:name] [np:[используемый]:np] [useon:-100] [text:Маленький огнетушитель одноразового действия, раскрашенный красными и белыми полосами.:text]'
end
:семена
! прибавить 160
if $args[0]='семена':
	$args['obj'] += '[:семена:] [name:Семена|Семян|Семенам|Семена|Семенами|Семенах:name] [np:[используемый]:np] [useon:160] [text:Мешочек с семенами. Из каждого семечка мгновенно вырастает ужасный сорняк, который убивает все растения вокруг, а потом засыхает сам.:text]'
end
:вервь
if $args[0]='вервь':
	$args['obj'] += "[:вервь:] [name:Верёвка|Верёвки|Верёвка|Верёвку|Верёвкой|Верёвке:name] [np:[верёвка]:np] [text:<DIN1:$args[0]=$func('prv.obj.inBag','вервь')
if $args[0]='ВЕРВЬ_000015':
	$args[111]='Длинная и прочная лиана, которую вам подарила Стрекоза. Прекрасно заменяет верёвку.'
end
$result=$args[111]:1DIN>:text]"
end
:ягода
if $args[0]='ягода':
	$args['obj'] += '[:ягода:] [name:Ягода|Ягоды|Ягоде|Ягоду|Ягодой|Ягоде:name] [np:[еда]:np] [text:Круглая мясистая зелёная ягода, которая в любой момент увеличит вашу СИЛУ на 5.:text] [eating:gosub "power",5:eating]'
end
:кольцо
! прибавить 40
if $args[0]='кольцо':
	$args['obj'] += '[:кольцо:] [name:Кольцо|Кольца|Кольцу|Кольцо|Кольцом|Кольце:name] [np:[кольцо][используемый]:np] [useon:40]  [text:Подарок мага. Кольцо, которое позволит взлететь... но лишь один раз... если повезёт...:text]'
end
:зеркало
! вычесть 268
if $args[0]='зеркало':
	$args['obj'] += '[:зеркалоо:] [name:Зеркало|Зеркала|Зеркалу|Зеркало|Зеркалом|Зеркале:name] [np:[используемый]:np] [useon:-268]  [text:Полуметровое зеркало в форме астры. Тонкое, прочное, и такое гибкое, что его можно скатать в трубку.:text]'
end
:шлем
if $args[0]='шлем':
	$args['obj'] += '[:шлем:] [name:Шлем|Шлема|Шлему|Шлем|Шлемом|Шлеме:name] [np:[доспех] [шлем]:np] [useon:-176] [text:Красивый рыцарский шлем. Пожалуй, в таком вас могут принять за настоящего рыцаря.:text]'
end
$args['obj']+=$args[1]	&	!	дополнительные параметры
if instr($args['obj'],'[pos:')=0: $args['obj']+='[pos:место_в_рюкзаке:pos]'
$result=$args['obj']

Storm:

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

Будет время, напишу и нарисую рабочую гексовую карту. Пока я не понимаю, зачем тебе центр гекса. Если проблема только в выводе на экран, то вычисление центра гекса ни к чему. Про три оси я как-то забыл. А ведь это удобнее! Попробую и так и так.

Storm:

“Меч”, у одного показатель урона 5, у второго 8.

Об этом я уже раза два писал в теме “как сделать”.))) Надо будет создать отдельную тему. Скорее всего ты зациклился на том, что предмет - это то, что выводится строкой в окне “инвентарь” (рюкзак). Нужно понять, что предмет - это абстракция, а то, что выводится в окне “инвентарь” - всего лишь пункт меню, который не обязательно является предметом. Так же как, например, диск в компьютере - это абстракция, так называемый логический диск. Логический диск может занимать часть физического, а может занимать несколько физических.
Если не воспринимаешь образ объекта, как сам объект, становится намного легче.
Вот мой движок (предупреждаю, он сильно не доработан). А вот тут я начал описывать, что он из себя представляет. Если не лень копаться в чужом коде, поищи для себя полезное.

Aleks Versus, если у тебя есть желание отвечать на мои вопросы, то я буду только рад выслушать, потому что в том коде, что ты привел в спойлере мне не всё понятно. Хотелось рассмотреть пример на каком-то одном объекте. Итак, начну с того, что мне понятно: это база предметов и она подключается отдельным файлом. Когда мы обращаемся к базе мы должны ей предоставить в $args[0] имя предмета, в $args[1] дополнительные параметры предмета(но я так и не понял их может быть несколько или всего одно содержащихся в этом элементе. Допустим $args[1]=“еда, питье”, или только так $args[1]=“еда”). А вот дальше мой мозг начал зависать от обработки информации :( Идентификатор класса $args[’obj’]+=“<obj> ” я вообще не понял за что отвечает. Дальше идем в оператор IF: получается если элемент массива $args[0] равен названию предмета, то выполняется ряд условий. И вот тут я снова завис на непонятных мне скобочках

$args['obj'] += '[:ночное_видение:] [name:Инфракрасные очки «Ночное зрение»|Инфракрасных очков «Ночное зрение»|Инфракрасным очкам «Ночное зрение»|Инфракрасные очки «Ночное зрение»|Инфракрасными очками «Ночное зрение»|Инфракрасных очках «Ночное зрение»:name] [np:[доспех] [очки] [инфракрасное зрение]:np] [text:Они позволяют видеть в темноте.:text]'

Получается элементу $args[’obj’] мы присвоили всё, что идет после равно. Но как то, что заключено в квадратные скобочки будет использоваться? Это регулярные выражения? К сожалению, я пока в них не вникал. Давай разберем на примере очков. Строчка “[:ночное_видение:]” не понятна вообще, могу только предположить что это свойство. Дальше “[name:Инфракрасные очки «Ночное зрение»|Инфракрасных очков «Ночное зрение»|Инфракрасным очкам «Ночное зрение»|Инфракрасные очки «Ночное зрение»|Инфракрасными очками «Ночное зрение»|Инфракрасных очках «Ночное зрение»:name]” - это то, что мы должны подставить в переменную name в зависимости от того, где в тексте встречается то или другое склонение выражения “Инфракрасные очки «Ночное зрение»”? Строка “[np:[доспех] [очки] [инфракрасное зрение]:np]” на сколько я понимаю это свойства предмета. Строка “[text:Они позволяют видеть в темноте.:text]” отвечает за описание предмета как я понимаю, но мне не ясно каким образом это всё будет выводиться. Что такое “text”? Это переменная?
Идем дальше. Посмотрел я примеры на мой вопрос о “мечах”. Я тоже обратил внимании, что если включен HTML, то то что внутри скобочек “<>” не будет отображено, но как-то не придал этому значения вначале, теперь вижу :) На сколько я понял, мы можем назначить индекс объекта в этих скобочках “<>”, тем самым вызывая именно тот объект, который нам нужен при клике на него. “oid” в показанном примере это идентификатор объекта, который мы должны извлечь в формуле

oid = val(mid($selobj,instr ($selobj,"<oid:")+5,len($selobj)-instr($selobj,':oid>')+5))

правильно я понимаю? Слово “регэксп”, к сожалению, тоже не понял от чего это аббревиатура :)
Твой движок со временем посмотрю, спасибо большое, извлеку что-то полезное для себя. Но мне так же будет интересно посмотреть на реализацию гексовой карты, ибо пока я это не могу представить в коде. А координаты центра гекса мне нужны, чтобы поставить на него определенный объект, пускай это будет какой-то человечек, зверек, враг или ещё кто-то). Или ты планируешь каждому гексу присваивать индивидуальный номер и опираясь на этот номер расставлять объекты?

Storm:

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

Storm, а вот ваши локации, они где хранятся? В астрале? Или тоже в памяти? И что получается когда вы обратились ко всем этим локациям? Переменные так или иначе все равно проинициализируются и займут свое место. Или, может быть, ваш код изобилует функциями KILLVAR? Я не понял из вашего объяснения, почему бы их не загрузить сразу оптом? Один gs, ИМХО, лучше кучи gs, разбросанных по коду.

UPD Регэксп (regexp) http://wiki.qsp.su/help:regexp

evp, локации хранятся в файле QSP, и обращаемся мы к ним через оператор GS только тогда, когда нам нужно. В том варианте что я делаю у меня просто добавляются характеристики к характеристикам персонажа когда мы одеваем какую-то вещь. Допустим, у главного героя есть параметр Сила[0]=10. Когда одевается предмет просто работает выражение Сила[0]=Сила[0]+[определенное число, для разных предметов оно разное], а когда снимается мы просто отнимаем это число.
Всё просто. Не вижу причин держать в памяти огромное количество неиспользуемых переменных. Но это просто объяснение, без множества дополнительных операторов, но суть ясна и так :)
У меня нету множества GS разбросанных по коду, и нету никаких KILLVAR, я серьезно :) Для предметов всего одно меню, именно это меню перенаправляет нас на эти все локации.
UPD: На локации которая находится в переменной $ONOBJSEL я пишу такой код

$si=$selobj
$itmm[0]="<<$si>>:Пустышка"
$itmm[1]='-:-'
$itmm[2]="Одеть:Выбор персонажа"
$itmm[3]='Снять:<<$si>>'
$itmm[4]='Доп. действие:<<$si>>'
$itmm[5]="Описание:<<$si>>"
$itmm[6]='Выкинуть:Выкинуть'
menu '$itmm'
unsel

Он отвечает за вывод меню. Локация “Выбор персонажа” выводит нам меню из имен персонажей партии, спрашивая на кого мы хотим одеть предмет. Далее, выбрав пунк меню мы попадаем на эту локацию, но в зависимости от того, какой именно пункт меню выбрал игрок выполняется действие. Вот и всё. Но это старая версия меню. Того что дал мне Aleks Versus мне хватит для того, чтобы значительно его улучшить, допустим сделать для разных типов предметов своё меню, осталось только освоить регулярные выражения, но это не сложно.
Код, что я тебе привел есть в примерах кода в файле objs.qsp, но Nex в теме “Как сделать?” показал как улучшить его, избавившись от лишних операторов. Я тебе привел уже свой вариант.
Конструкции кода, которые я придумываю, представляют собой общий вариант для определенного случая(в данный момент это база предметов), избавляя меня от огромного количества ненужного кода. Вариант со всеми предметами, которые при старте игры сразу же загоняются в память меня никак не устраивает, а QSP позволяет легко обойти это. Придется немножко дольше помучатся с кодом, но если представляешь как, то это не сложно. Это же касается и монстров.

Log in or Register to post comments.