Первое исправление, которое необходимо внести, это исправить ошибку отображении глубины текущего уровня подземелья в левом верхнем углу экрана. Основная идея заключалась в том, чтобы не перерисовывать каждый раз фоновое изображение экрана, а только изменяемые области: область карты, сообщений и параметров, что несомненно увеличит производительность программы. Однако, номер уровня, в результате, у нас выводится на не обновляемой области и, при смене уровня подземелья, может отображаться не всегда корректно. Исправляется это очень просто. Нужно добавить перерисовку фонового изображения при смене уровня.
dod.bas
Sub DrawMainScreen (db As Integer = FALSE)
Dim As Integer x, y, j, pct, row, col
Dim As Double pctd
Dim As UInteger clr
Dim As String txt, idesc
Dim As terrainids terr
Dim inv As invtype
Dim spl As spelltype
ScreenLock
'Нарисовать фон главного экрана
If db = TRUE Then
DrawBackground mainback()
End If
...Мы добавили для процедуры DrawMainScreen параметр, который указывает — нужно ли перерисовывать фон. Так как мы добавили параметр со значением по умолчанию, то нам не нужно вносить изменения везде, где вызывается эта подпрограмма, а только в том месте, где персонаж перемещается по лестницам.
dod.bas: Main Game Loop
...
'Главный цикл игры.
If mm <> mmenu.mQuit Then
'Установим первый ровень.
level.LevelID = 1
'Построим первый уровень подземелья
level.GenerateDungeonLevel
'Отобразим главный экран.
DrawMainScreen TRUE
...
'Проверим на передвижение вглубь по лестнице.
If ckey = ">" Then
'Убедимся, что лестница есть.
If level.GetTileID(pchar.Locx, pchar.Locy) = tstairdn Then
'Сменим номер уровня.
level.LevelID = level.LevelID + 1
'Построим новый уровень.
level.GenerateDungeonLevel
'Отобразим главный экран.
DrawMainScreen TRUE
End If
EndIf
...Мы должны обновить вызов процедуры в двух местах. В самом начале, после старта игры из главного меню, и при передвижении на персонажем по лестницам. Мы просто добавляем к вызову дополнительный параметр TRUE, в результате чего фоновое изображение будет также перерисовываться. Как видите — изменения в коде минимальны.
Следующее обновление связано с расходом опыта персонажа. Ткущая цена улучшения атрибутов, это 10 Опыта за 1 пункт атрибута. В результате персонаж может развиваться очень быстро, что позволяет ему «обмануть» игру. (я написал «обмануть» в кавычках потому, что на самом деле это не настоящий обман, а ошибка в игре, которой может воспользоваться проницательный игрок). Если игрок не будет тратить очки опыта до перехода на следующий уровень, а после перехода улучшить атрибуты персонажа, то его герой станет значительно сильнее монстров и запросто со всеми ими разделаться. Происходит это из за того, что мы масштабируем монстров, во время их создания, относительно текущих атрибутов персонажа.
Исправить это мы можем просто изменив соотношение опыта к атрибутам то 10 к 1 до 100 к 1. Это замедлит развитие персонажа и будет удерживать его характеристики в соответствии с характеристиками монстров. Игрок все еще может накапливать опыт до перехода на новый уровень, но теперь его превосходство над монстрами не будет таким большим.
dod.bas
'Применить опыт к атрибутам персонажа.
Sub ImproveCharacter ()
Dim As Integer sel, xp, reqamt = 100
'Убедимся что у нас достаточно опыта.
If pchar.CurrXP > reqamt Then
Do
If pchar.CurrXP > reqamt Then
'Print Current stats.
pchar.PrintStats
PutTextShadow "Cost = " & reqamt & " XP for 1 point improvement.", 49, 10
PutTextShadow "Enter attribute 1 to 5 to improve, enter to exit: ", 51, 10
'Позиция для ввода.
Locate 53, 10
'Ввод номера атрибута.
Input sel
'Изменим выбранный атрибут.
If sel = 1 Then
pchar.ChangeStrength 1
'Subtract the xp amount.
xp = pchar.CurrXP
xp -= reqamt
pchar.CurrXP = xp
EndIf
If sel = 2 Then
pchar.ChangeStamina 1
'Subtract the xp amount.
xp = pchar.CurrXP
xp -= reqamt
pchar.CurrXP = xp
EndIf
If sel = 3 Then
pchar.ChangeDexterity 1
'Subtract the xp amount.
xp = pchar.CurrXP
xp -= reqamt
pchar.CurrXP = xp
EndIf
If sel = 4 Then
pchar.ChangeAgility 1
'Subtract the xp amount.
xp = pchar.CurrXP
xp -= reqamt
pchar.CurrXP = xp
EndIf
If sel = 5 Then
pchar.ChangeIntelligence 1
'Subtract the xp amount.
xp = pchar.CurrXP
xp -= reqamt
pchar.CurrXP = xp
EndIf
Else
sel = 0
End If
Loop Until sel = 0
Else
PrintMessage "Not enough XP to spend."
End If
End SubМы добавили новую переменную reqamt в подпрограмму ImproveCharacter, которая указывает на количество затрачиваемого опыта для увеличения параметра персонажа. При использовании переменной, а не жестко заданного значения, мы, при необходимости, можем изменить это значение в одном месте, а не в нескольких. Может оказаться, что 100 это слишком много, поэтому это значение может потребоваться изменить еще раз. Нам будет легко попробовать разные значения, пока мы нащупаем правильную комбинацию.
Следующая настройка также связана с изменением параметров персонажа. Если обновляется сила или выносливость, то текущее и максимальное здоровье устанавливаются в соответствии с новыми значениями этими атрибутов. Этим может воспользоваться игрок для уменьшения проблем в игре. Исправим это, обновляя только значение максимально уровня здоровья, но не трогая текущее.
character.bi
...
Declare Sub ChangeStrength(change As Integer, docurrhp As Integer = FALSE)
Declare Sub ChangeStamina(change As Integer, docurrhp As Integer = FALSE)
...
'Изменение атрибута и обновление связанных параметров.
Sub character.ChangeStrength(change As Integer, docurrhp As Integer = FALSE)
'Обновим аттрибут
_cinfo.stratt(idxAttr) = _cinfo.stratt(idxAttr) + change
If _cinfo.stratt(idxAttr) < 1 Then _cinfo.stratt(idxAttr) = 1
'Обновим HP.
_cinfo.maxhp = _cinfo.stratt(idxAttr) + _cinfo.staatt(idxAttr)
If docurrhp <> FALSE Then
_cinfo.currhp = _cinfo.maxhp
End If
_cinfo.ucfsk(idxAttr) = _cinfo.stratt(idxAttr) + _cinfo.aglatt(idxAttr)
_cinfo.acfsk(idxAttr) = _cinfo.stratt(idxAttr) + _cinfo.dexatt(idxAttr)
_cinfo.cdfsk(idxAttr) = _cinfo.stratt(idxAttr) + _cinfo.aglatt(idxAttr)
End Sub
'Изменение атрибута и обновление связанных параметров.
Sub character.ChangeStamina(change As Integer, docurrhp As Integer = FALSE)
'Обновим аттрибут
_cinfo.staatt(idxAttr) = _cinfo.staatt(idxAttr) + change
If _cinfo.staatt(idxAttr) < 1 Then _cinfo.staatt(idxAttr) = 1
'Обновим HP.
_cinfo.maxhp = _cinfo.stratt(idxAttr) + _cinfo.staatt(idxAttr)
If docurrhp <> FALSE Then
_cinfo.currhp = _cinfo.maxhp
End If
_cinfo.currmana = _cinfo.intatt(idxAttr) + _cinfo.staatt(idxAttr)
_cinfo.maxmana = _cinfo.currmana
_cinfo.mcfsk(idxAttr) = _cinfo.intatt(idxAttr) + _cinfo.staatt(idxAttr)
End SubВ процедуры ChangeStength и ChangeStamina мы добавили флаг docurrhp со значением по умолчанию FALSE. И добавили условие, что если он равен TRUE (не равен FALSE), то только тогда изменяем также и текущий уровень здоровья. Больше никаких изменений в коде не требуется. Теперь, при увеличении атрибутов персонажа, его текущее здоровье не измениться.
Зачем мы добавили здесь какой то флаг вообще? Возможно мы захотим, в будущем, изменить и текущее здоровье при изменении атрибутов персонажа. Предположим что у нас есть заклинание, которое позволяет персонажу полностью восстановить здоровье при увеличении сили или выносливости. Теперь у нас есть способ сделать это без внесения дополнительных изменений в код. Даже если мы не будем добавлять никаких подобных механизмов, мы оставляем такую возможность открытой. В любом случае, это не повредит, даже если мы никогда не будем использовать эту функциональность.
Следующее изменение косметическое, но это одна из тех дополнительных возможностей, которые помогают игроку. Сейчас в инвентаре персонажа выделяются неопознанные предметы, мы также добавим выделение магических предметов, чтобы игроку не приходилось проверять все подряд для поиска предметов содержащих магические свойства.
dod.bas: DrawInventoryScreen
...
'Покажем игроку что предмет неопознан.
If ret = FALSE Then
txt &= "(*)"
Else
'Если содержит магию.
If inv.classid = clWeapon Then
If inv.weapon.spell.id <> splNone Then
txt &= " (M)"
End If
EndIf
EndIf
...Мы проверяем, опознан ли предмет, и если нет, то, как обычно, рисуем звездочку. Если же предмет опознан, то мы проверяем, оружие ли это и содержит ли оно магию, и, если это так, то мы отметим предмет буквой M. Это даст игроку возможность быстро узнать, без необходимости заходить в описание предмета, содержит ли он магию. Конечно, если предмет не опознан игроком, то он, все еще, не узнает, содержаться ли в нем какие либо магические свойства.
Последнее изменение также косметическое. Оно позволит игроку получить о персонаже более подробную информацию. Так как у нас теперь есть заклинания которые добавляют, на время, бонусы к атрибутам персонажа, то было бы неплохо отображать значение этих бонусов и их продолжительность, а не только сумму текущего значения и бонуса.
dod.bas: DrawMainScreen
...
If pchar.BonStr > -1 Then
txt = " +"
Else
txt = " -"
EndIf
PutText "Str: " & pchar.CurrStr & txt & pchar.BonStr & " (" & pchar.BonStrCnt & ")", row, col
...Приведенный пример кода показывает отображение бонуса для силы персонажа. Бонусы остальных атрибутов отображаются аналогичным образом. Так как мы позволяем использовать только один бонус одновременно, то эта информация поможет игроку решить, использовать ли предмет модифицирующий бонус параметра, или сохранить текущее значение.
Как вы можете видеть, все внесенные изменения очень просты в реализации, но имеют огромное влияние на игру. Изменение влияния опыта само по себе меняет всю динамику игры, будем надеяться, к лучшему. Это только первый этап настроек игрового процесса, в будущем, мы будем снова к этому возвращаться. Настройка игрового процесса это непрерывный процесс, и всегда есть что либо, что можно улучшить.
Комментариев нет:
Отправить комментарий