Форум » » Всякие полезные механики » Ответить

Всякие полезные механики

Ajenta: Пришло мне тут в голову, что у нас давно никто не делился опытом грабленаступания. Поэтому создаю тему, где все могут рассказать какими извратами и хитростями пользуются при написании игр. Начну вот с чего: Конечно, всегда хочется, чтобы игра была сложной, интересной и отвечала на все твои реакции. А для этого у одной и то й же локации должно быть много описаний. Сейчас как раз делаю игру, где у меня минимум пять описаний одного и того же места. Дабы не плодить сущности, можно делать так - :озеро if были_озеро = 1 then goto озеро_грязное if были_озеро = 2 then goto озеро_замёрзло if были_озеро = 3 then goto озеро_высохло if были_озеро = 4 then goto озеро_больше_не_озеро pln Описание end Удобно то, что всё это одна и та же локация, и курлок будет всегда одинаковым. Так же я не плодю безмерно условия в самой локации, а делю её, это очень помогает, потому что ифы это слабая сторона урки.

Ответов - 39, стр: 1 2 All

Ajenta: Продолжу. Когда пишешь код условий, он превращается порой в нечитабельное страшное нечто, в котором сложно что-то быстро поправить и сложно не наделать ошибок при этой самой правке. Приведу пример кода из своей последней игры. Как бы это выглядело, если бы было написано обычным способом if ледяной_показался = 0 then ледяной_показался = 1 & pln Войдя в пещеру, я тут же наткнулся на ледяного элементаля. Конечно же он попытался меня убить. Погонявшись за мной кругами по пещере и так и не догнав, он издал душераздирающий вопль и во все стороны полетели острые ледяные шипы. Но всё же, я успел выбраться из пещеры. Фуух. Это было опасно. & pln & pln & pln [[~ Отойти от пещеры.|ледник]] & proc ударить_молотом_ледника else pln С холодеющим сердцем, я зашёл в пещеру. Ледяной элементаль издал вопль радости и набросился на меня. Что ж, кажется, это была плохая идея. & if молот_взят = 1 then pln & pln & pln [[~ Ударить элементаля молотом.|элементаль_молот]] else anykey & goto провал Вроде бы и нормально, но мне не нравится. А теперь как это написано у меня в игре. if ледяной_показался = 0 then _ ледяной_показался = 1 & _ pln Войдя в пещеру, я тут же наткнулся на ледяного элементаля. Конечно же он попытался меня убить. Погонявшись за мной кругами по пещере и так и не догнав, он издал душераздирающий вопль и во все стороны полетели острые ледяные шипы. Но всё же, я успел выбраться из пещеры. Фуух. Это было опасно. & _ pln & pln & _ pln [[~ Отойти от пещеры.|ледник]] & _ proc ударить_молотом_ледника _ else _ pln С холодеющим сердцем, я зашёл в пещеру. Ледяной элементаль издал вопль радости и набросился на меня. Что ж, кажется, это была плохая идея. & _ if молот_взят = 1 then _ pln & pln & _ pln [[~ Ударить элементаля молотом.|элементаль_молот]] _ else _ anykey & goto провал Длиннее, но зато всё понятно - что в каком блоке и что вообще происходит.

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

Saint: О Великая и Ужасная гуру кода урки снизошла до нас с небес своей блистательной славы! (знаки препинания сами расставляйте) Я прям для себя нашел весчи интересные! Ну оно и понятно - опыта у Адженты ого-го!!! Продолжай!!!


Cheshire: Ajenta пишет: Длиннее, но зато всё понятно - что в каком блоке и что вообще происходит. Могу ещё посоветовать использовать табуляцию: [pre2]if ледяной_показался = 0 then _ ледяной_показался = 1 & _ pln Войдя в пещеру, я тут же наткнулся на ледяного элементаля... & _ pln & pln & _ pln [[~ Отойти от пещеры.|ледник]] & _ proc ударить_молотом_ледника _ else _ pln С холодеющим сердцем, я зашёл в пещеру. Ледяной элементаль издал вопль радости и набросился на меня. Что ж, кажется, это была плохая идея. & _ if молот_взят = 1 then _ pln & pln & _ pln [[~ Ударить элементаля молотом.|элементаль_молот]] _ else _ anykey & goto провал[/pre2]

Saint: Не всегда примеры в документации понятны, поэтому когда-то попросил Серого Волка мне помочь, и вот что он мне написал: zagadka=1 ; не отгадана, принимает значение 2 после отгадки :vopros1 pln Отгадай загадку! pln "Два кольца, два конца, посредине - гвоздик" btn vopros2, Ответить end :vopros2 instr otvet= input otvet pln - #%otvet$! - говоришь ты. if otvet="ножницы" or otvet="Ножницы" then zagadka=2 & pln Да, ты прав. Уж если ты прав, то ты прав! else pln А вот и нет! if zagadka=2 then btn konec, Ура! if zagadka=1 then btn vopros1, Пробуй ещё end :konec pln Ты с треском победил! end Отличный пример использования оператора input

Cheshire: На просторах интернета можно найти множество свободных шрифтов, в том числе символьных. (Например, такой — Sosa). Если в текстовом декораторе в ссылках использовать такой шрифт, то можно получить основанный на иконках интерфейс. [pre2]:0 decoradd one (350,250,0) text "[[c|%1]]", 0xFFFFFFFF, "sosa.ttf[25,1,0.3,0xFF000000]" decoradd two (450,250,0) text "[[e|%1]]", 0xFFFFFFFF, "sosa.ttf[25,1,0.3,0xFF000000]" decoradd three (350,350,0) text "[[9|%1]]", 0xFFFFFFFF, "sosa.ttf[25,1,0.3,0xFF000000]" decoradd four (450,350,0) text "[[j|%1]]", 0xFFFFFFFF, "sosa.ttf[25,1,0.3,0xFF000000]" decorcol one 0xFFFFFFFF,0xff999999,0xFFffffff decorcol two 0xFFFFFFFF,0xff990000,0xFFff0000 decorcol three 0xFFFFFFFF,0xff009900,0xFF00ff00 end :1 btn z, Раз btn z, Два btn z, Три end [/pre2] Результат.

Ajenta: Не знала что так можно O__o instr otvet= Это оно пустую строку присвоит что ли?

Ajenta: Вдруг кому-то понадобится. Вычисление приблизительного квадратного корня. Делала пример для Эдди, ему нужно было хитро как-то декораторы вращать, но мало ли ещё кому пригодится. :1 a = 500 ;ставь любое число, из которого хочешь извлечь корень pln число равно = #a$ i = 1 :metka if i < #a$/2 then pln мы тут & _ x1 = i+1 & pln x1 = #x1$ & ;вычисляем первое число по формуле Xn+1 = (A/Xn + Xn)*1/2 _ x2 = (a/i + i)*1/2 & pln x2 = #x2$ & ;вычисляем второе число по формуле Xn+1 = (A/Xn + Xn)*1/2 _ fp_prec=0 & ;эта фигню нужна, чтобы отбросить цифры после запятой _ int_x2=#x2$ & pln int_x2 = #int_x2$ & ;приводим второе число к целому значению _ if x1 = int_x2 then pln корень равен - #x1$ else i = i + 1 & goto metka end

vito: Ajenta пишет: Не знала что так можно O__o instr otvet= Это оно пустую строку присвоит что ли? Ага. Это равноценно otvet="" А я думала, только настоящие мачо не читают документацию :)

frodo: Дополню совет Адженты насчет пола персонажа. Иногда можно перефразировать предложение. Например: Ты встретил(а) друга. -> Тебе встретился друг.Ты захотел(а) уйти. -> Тебе захотелось уйти. Настоящее время вместо прошедшего (что естественно для ИЛ) решает почти все проблемы: Ты решил(а) остаться -> Ты решаешь остаться.Ты устал(а) -> Ты чувствуешь усталость. А если сменять точку зрения, предложение получится не только универсальным, но и более емким: Ты пошёл(ла) налево и встретил(а) своего давнего знакомого. -> Тропинка увела тебя налево, взгляд уловил вдали знакомый силуэт.

frodo: Если игрок нажимает на кнопку, которая оставляет его на прежней локации, текст должен хоть как-то меняться. Самый "ленивый" вариант - если в начале локации или в Common есть cls, дописывать к тексту пробел: [pre2] :нажать cls пробел = not пробел if пробел then p ; Обратите внимание, 2 пробела после p pln Ничего не произошло. btn нажать, Нажать на кнопку. end [/pre2] Конечно, пробел можно заменить любой фразой, а также использовать if/else. Вариант чуть получше - внедрять в текст различные варианты фраз: [pre2]:нажать cls retry0="" retry1=" снова" retry2=" еще раз" retry3=" снова" retry4=" опять" retry5=" вновь" summary0="Кажется," summary1="По-прежнему" summary2="Все-таки" summary3="Можно больше не пытаться -" summary4="Бесполезно -" summary5="Как и первый раз," if count_нажать then _ x=rnd5 & y=rnd5 _ else _ x=0 & y=0 pln Ты нажимаешь на кнопку#%retry#x$$. #%summary#y$$ ничего не происходит. btn нажать, Нажать на кнопку#%retry#rnd5$$. end[/pre2] Недостаток такого подхода: если у вас всего лишь 1 набор фраз, а не 3, как в примере, они могут повторяться дважды подряд. Тогда лучше использовать ротацию вместо rnd: [pre2]if x >= 5 then x = 1 else x = x + 1[/pre2] Вот мой шаблон для ротации двух несвязанных реплик: [pre2] ;первая реплика temp10="" temp20="" temp30="" temp40="" temp50="" ;вторая реплика temp11="" temp21="" temp31="" temp41="" temp51="" temp61="" реплика1=реплика1+1 реплика2=реплика2+1 if реплика1>5 then реплика1=1 if реплика2>6 then реплика2=1 pln #%temp#реплика1$0$ pln #%temp#реплика2$1$ [/pre2] Первая фраза дает нам 5 вариантов, вторая 6. Если моя память не изменяет мне со знаниями математики , такой шаблон будет генерировать уникальные комбинации реплик, которые начнут повторяться лишь после 5 * 6 = 30 (тридцати) вызовов. Замечу, что для того, чтобы шаблон работал, разность между количеством реплик должна быть простым числом (в нашем случае 5-6=1). Простые числа: 1, 2, 3, 5, 7, 11, 13, 17 ...

frodo: Пример цензуры, как в Памяти Вселенной. В настройках устанавливаем флаг "censured". В локациях пишем: [pre2] temp0 = "Вся правда, как есть!" temp1 = "Зайчики, цветочки" pln #%temp#censured$$ [/pre2] Горшочек, не вари! :)

Prime: Frodo, есть ещё один способ осуществить смену пола без подбора синонимичных универсальных предложений: :start Pln Ваш пол: xbtn 1,{okonchanie1=""&okonchanie2="ёл"}, Мужской. xbtn 1,{okonchanie1="а"&okonchanie2="ла"}, Женский. end :1 Pln Ты решил#%okonchanie1$ выйти из комнаты, и подош#%okonchanie2$ к двери. end

Saint: Пример использования оператора common. Пример был написан для игры "Бабочки, мосты, хоббиты" и был использован в игровом лабиринте. Пример не мой, но очень понятный и доступный к пониманию. Заводим локацию common_1 при входе в лабиринт включаем переменную common=1 при выходе снова common=0 :common_1 безумие = безумие+1 if безумие = 5 then pln Мимо нас пробежала сосед Фрого, за которым гналась его жена Мила, с деревянной скалкой в руках. Странно, они всегда были дружной семьей... if безумие = 7 then pln Из подворотни выскочил старый пес и молча попытался вцепиться Корвусу в ногу. Корвус стукнул его обухом по голове и пес успокоился, виновато завилял хвостом и ушел обратно в подворотню.#/$ - Не нравится мне это - сказал Кровн. if безумие = 9 then pln Из-за забора доносились крики, шум и детский плач.#/$ - Маркус колотит детей, а Роза бегает за ним с метлой - сообщил Корвус заглянув в окно. Мы должны торопиться! end Как-то так.

Ajenta: Prime пишет: Frodo, есть ещё один способ осуществить смену пола без подбора синонимичных универсальных предложений: :start Pln Ваш пол: xbtn 1,{okonchanie1=""&okonchanie2="ёл"}, Мужской. xbtn 1,{okonchanie1="а"&okonchanie2="ла"}, Женский. end :1 Pln Ты решил#%okonchanie1$ выйти из комнаты, и подош#%okonchanie2$ к двери. end Это лучше использовать в диалогах, когда нпц обращается к персу или говорит о нём. Там действительно от окончаний пола не отделаешься.

frodo: Еще нашел в своей копилке полезностей. Процедура, которая позволяет автоматически генерировать сообщения о том, что инвентарь пытаются использовать неправильно. Полезна еще как примар трех идей: аргументы по умолчанию, описание использования в комментариях, "говорящие" названия переменных (по умолчанию это="это", этим="этим"). А еще к тексту дописываются пробелы (см. мой предыдущий пост) [pre2]:set_noinv ; set_noinv("это", "этим", "Комментарий") ; Неправильное использование инвентаря ; if set_noinv_1 then это = set_noinv_1 else это = "это" if set_noinv_2 then этим = set_noinv_2 else этим = "этим" if set_noinv_3 then noinv = set_noinv_3 else noinv = "Ничего не произошло." if tab=" " then tab = "" else tab = " " noinv1=" #%noinv$" noinv2=" Здесь #%это$ нельзя применить." noinv3=" Тут с #%этим$ нечего делать." noinv4=" Наверное, #%это$ следует применить в другом месте." noinv5=" Может, применить #%это$ в другом месте?" noinv6=" #%noinv$" noinv7=" И что с #%этим$ делать?" noinv8=" Что-то сделать с #%этим$? Слабо представляется..." noinv9=" #%noinv$" noinv10=" Наверное, с #%этим$ не сюда." noinv11=" Скорее всего, #%это$ стоит отнести куда-нибудь еще." noinv12=" Здесь #%это$ нельзя пристроить." noinv13=" #%noinv$" noinv14=" Очевидно, #%это$ нужно применить не здесь." noinv15=" Наверное, есть другой вариант использовать #%это$." noinv = "#%tab$#%noinv#rnd15$$" end[/pre2] Процедура устанавливает значение переменной noinv. Обратите внимание - комментарий (строки вида 'noinv1=" #%noinv$"') повторяется несколько раз, так что будет появляться чаще других сообщений. Пример использования: [pre2]:Use_Поднос_Применить clst proc set_noinv("поднос", "подносом", "Нет, поднос тут определенно не нужен.") if <условие> then pln Кэл отмывает поднос от грязи. if <другое условие> then proc Поднос_Применить if not <условие> and not <другое условие> then pln #%noinv$ End[/pre2] P.s. Может быть, следует как-то каталогизировать советы? Напримпр, хранить в шапке перечень со ссылками.

frodo: Иногда приходится выдавать пользователю большое количество текста. Обычно я стараюсь выводить текст так, чтоб он занимал не более чем 2/3 экрана - тогда он легче читается и не так вызывает скуку. Обычно это выглядит как часть текста, которая обрывается на интересном месте - плюс единственная кнопка "Дальше". В "Памяти Вселенной" я попробовал еще один подход - тест выводится побуквенно, словно его кто-то печатает. Таким образом, читатель следит взглядом за словами, что появляются на экране в умеренном темпе. Если нажать любую клавишу, печать ускоряется, но лишь до определенной точки. Конечно, такой подход требует тонкой настройки - с какой скоростью выводить слова, какой кусок выводить, если была нажата кнопка и проч. Программно это выглядит так: [pre2] temp=50 ; Стандартная пауза между символами temp1=2000 ; Пауза в конце абзаца temp2=500 ; Пауза в конце строки proc не_ускорить ; Just in case ; Начинаем неспеша proc type_string(" Бедный, бедный Калашников... ", 150, 1) proc type_string(" Вот, пришел и мой черед тебя навестить. Это я, Марина.", 150, 1) proc не_ускорить ; Если пользователь нажал на любую кнопку, до этого места текст выскакивает быстро proc type_string(" Пару месяцев назад Мангуст рассказывал о Неизбежности. ", temp, temp2, 1) proc type_string("Знаешь смысл", temp, temp) ; Тонкая настройка, как было сказано proc type_string("этого слова?", temp, temp1) ; Чтобы текст шел плавно, перевод строки вставляем вручную proc type_string(" Представь, что на шкафу стоит ваза. Однажды тебе покажется, что она #/$ _разобьется. Ты лезешь на шкаф, чтобы спасти вещицу, и случайно роняешь. ", temp, temp1) [/pre2] А вот код этих двух процедур: [pre2] :type_string ;type_string_1 - строка ;type_string_2 - пауза между символами ;type_string_3 - пауза в конце ;type_string_4 - не делать перевод строки ;ускорить - глобальная, если не равна 0, символы выводятся без задержки. instr tokens_delim=char tokens type_string_1 i=1 :type_string_cycle p #%token#i$$ if ускорить = 0 then anykey ускорить, #type_string_2$ i=i+1 if i<=tokens_num then goto type_string_cycle if type_string_4=0 then pln if ускорить = 0 then anykey ускорить, #type_string_3$ end :не_ускорить ; Используется вместе с type_string. Сбрасывает глобальную переменную "ускорить". ; Если была возведена, пауза (2 сек. по умолчанию) if not ускорить then end if not не_ускорить_1 then не_ускорить_1 = 2000 ускорить = 0 anykey ускорить, #не_ускорить_1$ end [/pre2]

Ajenta: Круто, но слишком сложно для меня :) Я с токенами до сих пор не лажу.

frodo: Ajenta, ничего сложного. Как говорил Вицин в "Операции "Ы"", всё уже украдено до нас. Если лень разбираться, достаточно запомнить что этот код: [pre2]proc type_string("Печатаю текст", 50, 200)[/pre2] выведет "Печатаю тест" с паузами в 50мс между буквами и 200мс в конце вывода. Разберем по командам: [pre2] instr tokens_delim=char ; указываем оператору "tokens" разбивать строки на отдельные символы (иначе будет разбивать на слова - см. документацию); tokens type_string_1 ; Тут понятно - первый аргумент (строка "Печатаю текст") передается оператору tokens ; Оператор tokens заполняет переменные: token1="П", token2="е", token3="ч", ... , а также tokens_num=13 (количество токенов, в нашем случае равно длине строки "Печатаю текст") p #%token#i$$ ; Выводим буквы по одной if i<=tokens_num then goto ... [/pre2] Отдельно хочу указать на эту конструкцию: [pre2]if ускорить = 0 then anykey ускорить, #type_string_2$[/pre2] Это довольно полезная штука. Ее суть: "Делать паузы, пока пользователь не нажмет на кнопку. Если нажал, больше пауз не делать." Чтобы паузы опять выполнялись, нужно переменную "ускорить" установить в 0. Если у вас в квесте пользователю приходится ждать больше 3 секунд, возьмите на вооружение, т.к. тех, кто будет проходить квест второй раз, ожидание будет раздражать.

Ajenta: Спасибо за пояснения. :)



полная версия страницы