RU

Переменные. Как сделать проигрыш на любой локации?

BigForest #468 21.12.2011 04:13 37 comments 25725 views

Вопрос.
Мне нужно, чтобы персонаж умирал на любой локации, если здоровье у него становится меньше 10?

Edited at 21.12.2011 04:30 (14 years ago)

Aleks Versus:

почему неверный?

Nex:

появляется зависимость от реалтайма

Ну вот представь. На ГГ в игре, допустим, упало дерево. Отнялось 50 жизней, было 40. Итого у тебя стало жизней < 0. Если проверка у нас в каунтере, то полсекунды или около того мы будем видеть на экране то, что должно нам показываться, если мы выжили, а потом экран поменяется на соответствующий смерти игрока. Если делать вызов каунтера чаще, сути это не изменит. Допустим, у нас на следующей локации какой-нибудь “родник силы”, который полностью исцеляет игрока. Получится, что несмотря на то, что дерево убило игрока, труп дошел до источника и исцелился. Таким образом, это в любом случае приводит к багам.

Проверка должна быть там, где значение изменяется, сразу же после изменения. Если проверка простая(как в том примере что я приводил), то можно скопировать ее во все места кода, где изменяется значение переменной. Если код проверки более сложный, можно выделить отдельную локацию для проверок и вызывать ее с помощью GS, опять же во всех местах, где меняется значение.

Nex, что-то непонятно объясняешь. Зачем в onnewloc, ведь тогда придется перейти на другую локацию, чтобы умереть-то!

Winter Wolf,
ONNEWLOC - способ если изменения должны происходить при переходе между локациями. А то о чем я писал сообщением выше, никак не связано с ONNEWLOC.
Есть два приемлемых варианта:
1. делать проверку при переходе на новую локацию(ONNEWLOC)
2. делать проверку сразу же при изменении значения(описано в сообщении выше)
Какой выбрать - решать автору. Выбор зависит от того, как он строит свою игру.

Например, у ГГ с течением времени растет параметр “голод”. При голод >= 50 в описание локации пишется “вы голодны”, при голод >= 80 “вы чрезвычайно голодны”, при голод >= 90 “вы умираете от голода”, при голод >= 100 ГГ умирает. Изменение параметра, проверку на смерть от голода и вывод предупреждающих сообщений удобнее всего будет сделать в ONNEWLOC. Каждый переход с локации на локацию будет постепенно увеличивать “голод”, и игроку придется следить за тем, чтобы ГГ не голодал.

Если же реакция на изменение параметра должна быть моментальная, то и проверку следует делать сразу же после изменения переменной.
Вот так:

'На вас упало дерево.'
здоровье = здоровье - 50
IF здоровье <= 0:
  XGOTO 'смерть'
END

или так:

'На вас упало дерево.'
здоровье = здоровье - 50
GS 'проверка_здоровья'
Aleks Versus Moderator 08.01.2012 19:39 (14 years ago)

Понятно. Оставляем выбор за автором. Тут будет неправильно говорить, что проверка того или иного параметра через каунтер - это неправильный подход. Если автор уверен, что такая проверка не даст ему багов, почему бы ему не сделать через каунтер? :=D Постоянно помнить в голове, что мне нужно после каждой формулы расчёта здоровья ставить проверку здоровья, писать каждый раз пару лишних строк - спасибо, я слишком ленив :=D . А так - да, лучше проверять именно в том месте, где это необходимо.

А не является ли проблема “вписал проверку не в том месте” очередными граблями?

Тут будет неправильно говорить, что проверка того или иного параметра через каунтер - это неправильный подход.

Нет, это в корне неправильный подход. Просто ты еще не до конца разобрался в QSP.

Если автор уверен, что такая проверка не даст ему багов, почему бы ему не сделать через каунтер?

Потому что это в любом случае ведет к багам.

мне нужно после каждой формулы расчёта здоровья ставить проверку здоровья

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

писать каждый раз пару лишних строк - спасибо, я слишком ленив

Во-первых, код проверки прекрасно укладывается в один оператор GS, я выше приводил пример. Можно даже короче записать, например:

GS 'здоровье', -50

в локации “здоровье” будет изменяться параметр “здоровье” и заодно будет осуществляться проверка.
Во-вторых, автор имеет право лениться писать правильный код. Пусть только помнит о том, что тем самым он обрекает игрока на встречу с багами.

А не является ли проблема “вписал проверку не в том месте” очередными граблями?

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

Nex:

Если автор уверен, что такая проверка не даст ему багов, почему бы ему не сделать через каунтер?

Потому что это в любом случае ведет к багам.

Даже больше скажу, в Android плеере на телефона слабее, чем ПК, это будет ОЧЕНЬ тормозить и будет обидно.

Как сделать отдельную комнату для всех переменных, которые часто меняются в течении игры? Если их ставить в начале комнаты, а потом в другой комнате поменять им значение, и вновь перейти в комнату где она задавалась, то переменная принимает изначальное значение. Я сделал эти переменые в начальной комнате, но их очень много и комната захламляется переменными, это вроде не критично но не удобно. Есть ли способ?

Ну сделай спец локацию для определения переменных и вызовами её из начальной, используя gs

TeRV,
ты можешь создать локацию с любым именем, например “переменные”, вписать туда все что нужно в поле “выполнить при посещении”, а в начале игры вызвать ее вот так:

GS 'переменные'

А вообще чтобы не возникало таких ситуаций “в другой комнате поменять им значение, и вновь перейти в комнату где она задавалась, то переменная принимает изначальное значение”, нужно пользоваться таким приемом:

IF был_на_локации_лес = 0:
  был_на_локации_лес = 1
  ...НУЖНЫЕ НАМ ОПЕРАТОРЫ(например, установка переменных для этой локации)...
END

В приведенном примере, операторы выполнятся только один раз, при первом заходе на локацию.

Спасибо, я как-то пробовал gs но он почему-то не сработал, сейчас же всё работает… странно =)

Aleks Versus Moderator 12.01.2012 09:14 (14 years ago)

Nex:

Потому что это в любом случае ведет к багам.

Не верю. Проверю

Nex:

Нет, это в корне неправильный подход.

Из-за привязки к текущему времени? Это как-то связано с частотой процессора, шин, или чего либо ещё?

Nex:

Не могу представить себе такой ситуации

Ты только что сказал, что ставить проверку в каунтере - это в корне неверный подход. :=D Значит грабли?

Nex:

Вообще-то в игре формула должна быть только в одном месте

Логично. Можно вообще написать подпрограмму для каждой формулы, потом только вызывать их через gs|func. Однако у меня нет уверенности, что я смогу вызвать такую подпрограмму в любом месте игры (есть ведь ограничения на количество вызываемых друг из друга подпрограмм, или нет?), поэтому сначала всегда пишу формулу целиком там, где она нужна.

А вот эта идея вбить формулу расчёта и проверку в одну подпрограмму и вызывать лишь там, где нужно, - мне нравится. Почему-то не приходило в голову. Вместо постоянного health=health-x, вписывать что-то вроде gs ‘estimate_health’,x где x - отымаемое здоровье, а код локации estimate_health:

health=health-args[0]
if health<1: XGOTO 'умер'

Ведь можно и посложнее. Скажем передавать во втором, третьем и прочих аргументах различные варианты описания произведённого эффекта (”помер”, “выжил”, “держусь на силе воли”). Получается намного динамичнее, чем тупой отсыл к локации смерти через тот же каунтер, и при этом нет необходимости всякий раз прописывать одни и те же конструкции.
Это откровение! Я прозрел! И это не сарказм. Спасибо, Nex.

И всё таки, как насчёт ограничений на вложенность подпрограмм, вызываемых через gs|func?

Не верю.

Да на здоровье. Тут нужно просто хорошо понимать логику работы движка QSP, тогда это станет очевидным.

Из-за привязки к текущему времени? Это как-то связано с частотой процессора, шин, или чего либо ещё?

Не из-за привязки ко времени.
1. Как правило, игрок видит текст события, в котором “проверка выполнилась”, а потом “вдруг” экран меняется(проверка не выполнилась), получается этакий эффект “дергания”. Выглядит очень неприятно.
2. Игрок может совершить действие, когда локация-счетчик еще не выполнилась. Выше описывал пример.
3. Архитектурно это неправильно, проверять постоянно то, что должно проверяться только при изменении значения - однажды. Лишние накладные расходы на процессорное время, а если проверок очень много, это может стать критичным.

Ты только что сказал, что ставить проверку в каунтере - это в корне неверный подход. big_smile Значит грабли?

Если имелась в виду проверка с помощью каунтера - то да, это грабли. Видимо я просто не понял твой вопрос.

как насчёт ограничений на вложенность подпрограмм, вызываемых через gs|func?

У меня вложенные GS выполнялись до глубины 2745. Явно заданного ограничения нет, при превышении некого порога(2745 в моем случае) плеер просто вылетает с ошибкой. По-хорошему в играх не должно быть очень глубоких вызовов. Если они есть, значит автор неправильно спроектировал код.

Aleks Versus Moderator 12.01.2012 17:14 (14 years ago)

Ох я тут нафлудил, однако тема животрепещущая.

Nex:

Тут нужно просто хорошо понимать логику работы движка QSP

Для понимания этой логики нужно вникать в исходный код?

Nex:

Если имелась в виду проверка с помощью каунтера - то да, это грабли. Видимо я просто не понял твой вопрос.

Я не точно выразился. Прошу прощения. Имелась ввиду именно проверка с помощью каунтера - то, что я подразумевал под словами “вписал в не том месте”.

Nex:

GS выполнялись до глубины 2745

Это с передачей аргументов? Надо тоже попробовать.

Для понимания этой логики нужно вникать в исходный код?

Нет, достаточно просто хорошо разбираться в написании QSP-игр.

health=health-args[0]
if health<1: XGOTO 'умер'

У меня похоже реализовано: есть лока отвечающая за жизнь, в неё передаются инструкции.

if $args[0]='damage':
cur_hp=cur_hp-args[1]
!тут ещё проверка на смерть
end
if $args[0]='heal':
cur_hp=cur_hp+args[1]
if cur_hp>max_hp:cur_hp=max_hp
end
if $args[0]='regen':
!эта лока вызывается по таймеру для постепенной регенерации
if cur_hp<max_hp:cur_hp=cur_hp+1
end

Log in or Register to post comments.