суббота, 21 июля 2012 г.

Давайте сделаем рогалик. Глава 27: Балансируем уровень сложности

Так как теперь мы уже совсем близки к полноценной игре, давайте остановимся на минуту и посмотрим — можно ли сделать ее более играбельной? Сейчас сложность игры достаточно высока и мы должны сбалансировать ее таким образом, чтобы облегчить игру на ранних уровнях и постепенно усложнять ее к более глубоким уровням подземелья. Мы можем добиться этого путем балансировки уровня сложности. Уровень сложности у нас заключается в шансе опознать предмет, значениях параметров характеристик монстров, сила атаки монстров и уровень их брони. Для того, чтобы облегчить жизнь игроку на начальных этапах игры, будем масштабировать значения этих параметров в зависимости от глубины уровня подземелья.


Поможет нам в этом новая функция, которую мы добавили в файл utils.bi

utils.bi
'Возвращает фактор масштабирования основанный на текущем уровне подземелья.
 Function GetScaledFactor(basevalue As Integer, currlevel As Integer) As Integer
   Dim As Double pct
   Dim As Integer ret, range, fac, fac2 
 
   'Получим фактор текущей глубины подземелья.
   pct = currlevel / maxlevel
   'Получим диапазон базовой величины.
   range = basevalue * .25
   'Получим фактор основываясь на 25%-ом диапазоне.
   fac = RandomRange(-range, range)
   'получим возвращаемое значение, как сумму базового и 25% интервала
   ret = basevalue + fac
   'Получим изменение значения зависящее от уровня.
   fac2 = (ret * pct) + 1 
   'Добавим к возвращаемому значению, значение зависящее от уровня.
   ret = ret + fac2
 
   Return ret
 End Function

GetScaledFacor использует базовое значение величины и глубину уровня подземелья для расчета масштабированного значения. Возвращаемое число будет на 25% больше или меньше базового, плюс значение, зависящее от текущей глубины уровня подземелья, которое будет стремиться к 100% базовой величины по мере приближения персонажа к самому нижнему уровню подземелья.

Мы сохраняем процентный коэффициент, зависящий от глубины уровня в переменной prc. Далее мы получаем значение величины диапазона, рассчитанное как 25% от базовой величины и берем случайное число, лежащее в пределах от отрицательных значений величины диапазона, до положительных. Полученную величину добавляем к базовому значению. Суммарное значение, зависящее от уровня, сохраняется в переменное fac2, которое будет иметь минимальное значение 1, но будет приближаться к 100% от базовой величины по мере продвижения персонажа к нижним уровням подземелья. Fac2 затем добавляется к рассчитанному измененному значению (+-25% от базового) и возвращается из функции.

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

monster.bi
...
   'Зададим атрибуты монстров.
   mon.id = RandomRange(monDarkangel, monGriffon)
   stratt = GetScaledFactor(pchar.CurrStr, currlevel)
   staatt = GetScaledFactor(pchar.CurrSta, currlevel)
   dexatt = GetScaledFactor(pchar.CurrDex, currlevel)
   aglatt = GetScaledFactor(pchar.CurrAgl, currlevel)
   intatt = GetScaledFactor(pchar.CurrInt, currlevel)
 ...

Здесь мы генерируем значения параметров характеристик монстров в зависимости от значений этих параметров у персонажа +-25%, увеличивая получаемые значения по мере приближения персонажа к дну подземелья. Если персонаж опуститься в глубь подземелья, то он скоро узнает, что монстры, обитающие на глубине, значительно сильнее своих предшественников. С другой стороны, игроку, возможно, понадобиться быстро спуститься на несколько уровней подземелья, и монстры будут увеличиваться в силе соизмеримо с персонажем, так как их характеристики все же основаны на соответствующих значениях его параметров.

Следующее место, где учитывается уровень сложности, это процедура опознания предметов.

inv.bi:GenerateWeapon
...
   'Magic item.
   If IsMagic = TRUE Then
      inv.weapon.evaldr = GetScaledFactor(charint, currlevel)
      inv.weapon.spell = 0
   EndIf
 ...

Здесь мы видим часть процедуры генерации оружия. Мы используем глобальную переменную charint, содержащую значение текущего интеллекта персонажа, для определения сложности опознания предмета. Мы используем здесь глобальную переменную, так как процедуры работы с инвентарем определены ранее объекта персонажа и пока не существуют для компилятора на данном этапе выполнения программы. Это, конечно, криво, но работает. Все остальные значения переменных evaldr задаются таким же образом.

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

monster.bi:GenerateMonster
...
   'Установим скорректированное значение атаки.
   mon.atkdam = mon.atkdam * pct
   If mon.atkdam < 1 Then mon.atkdam = 1
   'Установим скорректированное значение брони.
   mon.armval = mon.armval * pct
 ...

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

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

Комментариев нет:

Отправить комментарий