Как сделать?
…
kolvados,
cleep,
схема календаря не важна, если игровое время считается в минутах. Оба кода (JDN и :loop) по факту пересчитывают все прочие значения исходя из прибавленного количества минут. Только последний код не использует переменную time для хранения игрового времени, прошедшего с начала игры, а сразу делает перерасчёт по всем значениям: часы, дни, недели. Оба этих кода будем называть календарями.
Чтобы календарь создавал в игре правильное текущее время, необходимо выполнять его код всякий раз, когда время изменяется. Для первого календаря (JDN) необходимо изменять переменную time. Например:
act 'Идти в гости к бабушке':
! дорога до бабушки 2 часа
time = time + 2*60
! здесь ставим код календаря
end
Поскольку это очень громоздко (каждый раз при изменении времени воротить такой огромный код), календарь оформляют в отдельную локацию и вызывают через GOSUB (например календарь мы поместили на локации ‘Календарь’):
act 'Идти в гости к бабушке':
! дорога до бабушки 2 часа
time = time + 2*60
! вызываем календарь:
GOSUB 'Календарь'
end
Для второго случая, где используются циклы (через метки :loop), то же самое можно записать так:
act 'Идти в гости к бабушке':
! дорога до бабушки 2 часа
minute = minute + 2*60
! вызываем календарь:
GOSUB 'Календарь'
end
или так
act 'Идти в гости к бабушке':
! дорога до бабушки 2 часа
hour = hour + 2
! вызываем календарь:
GOSUB 'Календарь'
end
Приблизительно такая же ситуация и с голодом. Вот уже пару недель перечитываю тему “Как сделать”, и там этот вопрос раза три-то точно поднимался.
Голод должен изменяться периодически, т.е. через равные промежутки времени его значение увеличивается (герой становится голоднее). Например, каждые двадцать минут на единицу. Но, время, которое герой тратит на действия не всегда кратно двадцати минутам, и это надо учитывать, “запоминая” остаток времени для пересчёта голода.
Возьмём для примера два действия “Покрасить забор” (4 часа 43 минуты) и “Постоять потупить, глядя на часы, ровно 7 минут” (7 минут), и рассмотрим их в контексте календаря JDN.
За четыре часа сорок три минуты герой успеет проголодаться на 14 единиц , но при этом останутся три неучтённые минуты.
За 7 минут герой успеет проголодаться на 0 единиц и останется 7 неучтённых минут.
Исходя из этих двух случаев несложно составить маленький код, вычисляющий значение голода для двух конкретных действий:
act 'Покрасить забор':
! красим забор за 4 часа и 43 минуты
time = time + 4*60 + 43
! вызываем календарь:
GOSUB 'Календарь'
! считаем голод
голод = голод + (4*60 + 43 + голод_остаток)/20
! запоминаем остаток минут, чтобы добавить в другой раз
голод_остаток = (4*60 + 43 + голод_остаток) MOD 20
end
act 'Постоять потупить, глядя на часы, ровно 7 минут':
! стоим тупим семь минут
time = time + 7
! вызываем календарь:
GOSUB 'Календарь'
! считаем голод
голод = голод + (7 + голод_остаток)/20
! запоминаем остаток минут, чтобы добавить в другой раз
голод_остаток = (7 + голод_остаток) MOD 20
end
Как мы видим, из действия в действие код повторяется, а значит его можно вынести в отдельную локацию, а потом просто обращаться к ней по GOSUB, чтоб не писать один и тот же код всякий раз. Но, в разных действиях у нас разные значения. В “покрасить забор” – одно, в “постоять потупить” – другое. Как быть?
Всё очень просто. Дело в том, что локация может получать несколько значений и хранить их ровно то время, пока выполняется её код. Для передачи значения, нужно указать его через запятую после названия локации, например:
GOSUB 'улётная_лока',455
Чтобы использовать это значение на локации, берём специальные переменные args[], значения которых работают только на этой конкретной локации. На всех других локациях значения переменных args[] будут другими. Применим это знание к нашему коду. Создаём локацию “изменение_времени”:
!#изменение_времени
! вызывать например так GOSUB 'изменение_времени',7
args[0]=args[0] & ! значение этой переменной для примера равно 7. См. строку выше
! изменяем время
time = time + args[0]
! вызываем календарь:
GOSUB 'Календарь'
! считаем голод
голод = голод + (args[0] + голод_остаток)/20
! запоминаем остаток минут, чтобы добавить в другой раз
голод_остаток = (args[0] + голод_остаток) MOD 20
end
Теперь переписываем действия “покрасить забор” и “постоять” согласно нашей новой локации:
act 'Покрасить забор':
! красим забор за 4 часа и 43 минуты
GOSUB 'изменение_времени',(4*60 + 43)
end
act 'Постоять потупить, глядя на часы, ровно 7 минут':
! стоим тупим семь минут
GOSUB 'изменение_времени',7
end
Всё чертовски упростилось, не правда ли?
P.S.: Для календаря с loop вместо time нужно использовать minute. Числовые значения будут те же.
Aleks Versus,Благодарю за столь подробное разъяснение сия вопроса.
Но тем не менее вопрос встречный: (несколько раз перечитал сообщение) но так и не понял откуда берется голод_остаток в смысле как вычисляется?
kolvados,
это остаток от деления времени, которое потрачено на действие, на время, которое требуется, чтобы голод увеличился на единицу.
В примере голод возрастает на 1 каждые двадцать минут. Поэтому, если на действие тратится 4 часа 43 минуты (283 минуты), то за это время голод возрастёт на 14 единиц и ещё 3 минуты останутся неучтёнными. Их записываем в голод_остаток. При следующем действии в вычислении нам необходимо приплюсовать этот остаток к потраченному на действие время, чтобы учесть. Поэтомуголод_остатокя сразу вставил в формулу.
Возможно это не слишком удачное название переменной. Но называть её неучтённое_время_на_голод слишком громоздко.
Остаток от деления вычисляется оператором MOD
283 MOD 20 = 3
7 MOD 20 = 7
20 MOD 20 = 0в QSP эквивалентно:
283 - (283/20)*20
Aleks Versus, Вопрос в другом. Т.к. в коде никак не прописывается то, что остаток от деления присваивается этой переменной, мне не понятно это делает сама программа или я сам в ручную должен это сделать?
kolvados,
как это не прописывается?
Aleks Versus:
голод_остаток = (7 + голод_остаток) MOD 20
Действия игроком могут выполняться в произвольном порядке. Если он выберет “покрасить забор” а потом “потупить” произойдёт следующее:
в действии “покрасить забор” будет вычислен голод и остаток времени (голод_остаток) равный 3 минуты.
в действии “потупить” нужно учесть этот остаток. Поэтому он сразу вставлен в формулу и прибавляется к тем семи минутам, что мы тратим на действие “потупить”.
Но если действия будут выполняться игроком в обратном порядке, то сначала будет выполнено действие “потупить” и в остаток запишется 7 минут. Когда игрок выберет “покрасить забор”, нужно прибавить эти семь минут ко времени на действие, поэтому остаток тоже заранее внесён в формулу.
P.S.: Мне казалось, это очевидно, но очевидно не очевидно. )) Надо будет учесть.
Aleks Versus, Спасибо. Видимо я продолжаю тупить вместо того, чтобы красить забор.
cleep:
kolvados, привет, сразу говорю, что не эксперт)
Лучше бы ты заменил код времени на более простой. Например:
!!!Время !!минуты в часы :loopminute if minute>=60: hour+=1 gs 'gs_время' minute-=60 jump'loopminute' end !!часы в сутки :loophour if hour>=24: day+=1 dayspast+=1 weekday+=1 hour-=24 jump'loophour' end !!Цикл дней недели :loopweek if weekday>7: weekday-=7 jump'loopweek' end !!Дни в месяцы :loopmonth !это еще и годовая метка, ибо смена года влияет на високосность !Благодаря этому ифу, мы прервем конвертацию дней в месяцы, если месяцев набралось более чем на год. Сначла месяцы в год, потом возвращаемся снова к дням в месяцы. if month<13: !Невисокосный февраль if month=2 and day>28 and year mod 4!0: month+=1 day-=28 jump'loopmonth' end !Високосный февраль if month=2 and day>29 and year mod 4=0: month+=1 day-=29 jump'loopmonth' end !Январь, март, май, июль, август, октябрь, декабрь if (month=1 or month=3 or month=5 or month=7 or month=8 or month=10 or month=12) and day>31: month+=1 day-=31 jump'loopmonth' end !Апрель, июнь, сентябрь, ноябрь if (month=4 or month=6 or month=9 or month=11) and day>30: month+=1 day-=30 jump'loopmonth' end end !!месяцы в годы if month>12: year+=1 month-=12 jump'loopmonth' end !Сопоставление текстового названия дня недели его числовому значению if weekday=1:$weekday='Понедельник' if weekday=2:$weekday='Вторник' if weekday=3:$weekday='Среда' if weekday=4:$weekday='Четверг' if weekday=5:$weekday='Пятница' if weekday=6:$weekday='Суббота' if weekday=7:$weekday='Воскресенье' !тоже самое, только для месяцев if month=1:$month='Января' if month=2:$month='Февраля' if month=3:$month='Марта' if month=4:$month='Апреля' if month=5:$month='Мая' if month=6:$month='Июня' if month=7:$month='Июля' if month=8:$month='Августа' if month=9:$month='Сентября' if month=10:$month='Октября' if month=11:$month='Ноября' if month=12:$month='Декабря' !преобразовывает, например, 9 часов в 09 часов if hour<10:$nullh='0' if hour>=10:$nullh='' !тоже самое, но для минут if minute<10:$nullm='0' if minute>=10:$nullm=''Сам в начале работал с тем, что у тебя, но потом забил)
Что касается убывания, то здесь:
:loopminute if minute>=60: hour+=1 gs 'gs_время' minute-=60 jump'loopminute' endВ gs ‘gs_время’ прописываешь gg[’голод’]-=1 (или как там у тебя голод обозначается) и все должно работать
P.S. Если решишь использовать этот код, то формат вывода:
pl’Время <B><<$nullh>><<hour>></B>:<B><<$nullm>><<minute>></B>’
pl’Сейчас <<day>> <<$month>> <<year>> года, <<$weekday>>.’
Код вывода нужно использовать непосредственно в каждой локации или можно разово закинуть в статистику?
Лисий дух, достаточно закинуть в статистику
Лисий Дух,
окно дополнительного описания не очищается при переходе на новую локацию. Чтобы не было “размножения”, поставь перед строками вывода команду clear (clr).
Aleks Versus, спасибо.
Разобрался, неправильно задал переменную
Появился еще один вопрос:
Как реализовать следующее - если игрок оставляет поле ввода пустым - рост устанавливается по умолчанию и его переносит в следующую локацию?
Вот что есть:
$рост = input(’Введите рост Вашего персонажа в сантиметрах (см):’)
if $пол = 1 and $рост <= 169: msg(’Слишком маленький рост’)
if $пол = 1 and $рост >= 211: msg(’Слишком большой рост’)
if $пол = 0 and $рост <= 144: msg(’Слишком маленький рост’)
if $пол = 0 and $рост >= 186: msg(’Слишком большой рост’)
else
if $пол = 1 and $рост >= 170 and $рост <=210: gt ‘Начало’
if $пол = 0 and $рост >= 145 and $рост <=185: gt ‘Начало’
end
Здравствуйте. Недавно начал изучение QSP, появилось несколько трудностей:
1. Как зациклить проигрывание аудио? Желательно с примером. (Знаю что здесь вопрос уже поднимался но разобраться не удалось).
2. Как сделать переход между тремя локациями A B C по схеме: локация А - кнопка перехода на локацию В - на локации В ожидание несколько секунд и автоматический переход на локацию С.
Заранее спасибо.
Лисий Дух,
твой код неправильный, либо вырван из контекста, отчего неправильно читается.
:вводим_рост
рост = input('Введите рост Вашего персонажа в сантиметрах (см):')
if рост = 0:
! если игрок ничего не ввёл
if пол = 1: рост=186
if пол = 0: рост=167
goto 'Начало'
else
if пол = 1 and рост <= 169: msg('Слишком маленький рост') & jump 'вводим_рост'
if пол = 1 and рост >= 211: msg('Слишком большой рост') & jump 'вводим_рост'
if пол = 0 and рост <= 144: msg('Слишком маленький рост') & jump 'вводим_рост'
if пол = 0 and рост >= 186: msg('Слишком большой рост') & jump 'вводим_рост'
if пол = 1 and рост >= 170 and рост <=210: gt 'Начало'
if пол = 0 and рост >= 145 and рост <=185: gt 'Начало'
end
Числовые переменные пишутся без знака $. Различай однострочные и многострочные формы записи, и лучше всегда используй многострочные. Если не знаешь, что такое однострочные и многострочные формы if и act, то в старой справке это объясняется, целый раздел под многострочные отведён. Либо воспользуйся поиском по форуму.
Vlad,
зациклить аудио:
!самая первая локация в игре
$counter = 'counter'
!создаёшь локацию counter и пишешь в ней
if isplay('путь к мелодии/мелодия.mp3')=0:
play 'путь к мелодии/мелодия.mp3'
end
Того, что ты описал во втором вопросе, лучше не делать. Вернее: так делать плохо. Но делается это так. В локации B в поле выполнить при посещении:
wait 5000 & ! задержка пять секунд
goto 'C'
Aleks Versus, спасибо.
Aleks Versus,спасибо. Но хотелось ещё кое-что уточнить. Почему переход во втором вопросе нежелателен?
