Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Особенности национального бизнеса" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Создание ролевой компьютерной игры 16) Одеваем предметы из рюкзака, бросаем и подбираем
Информационный Канал Subscribe.Ru |
Разработка ролевой игры16) Одеваем предметы из рюкзака, бросаем и подбираем
Основываясь на своем опыте, хотелось бы внести ряд предложений:
Скачать вариант Андрея можно тут: Напоминаю всем еще раз, что версия, описываемая в данной рассылке - учебная. Я же специально об этом писал, и в контексте про два слота в частности :) А уж вы сами на базе этого кода можете что угодно сделать свое. И, воспользоваться правильными советами Андрея. От Павла письмо.
Я как-то писал вам, что параллельно с Вами делаю РПГ-игру на Visual C++. Про ДОС-кодировку я тоже писал, - в соответствующем месте :) - что она в win-формате, и ее надо ручками переделывать. Так что тем, кто хочет просто "посмотреть на "код текущей версии"" - также рекомендуется посмотреть и текст текущей версии рассылки :) Ох, по поводу defines.inc, СПАСИБО! Добавлен этот файл в текущий код. Я обычно архив делаю командой
pkzip xxx.zip *.pas И присылайте ваш код на С++, опубликуем. Одеваем предметы из рюкзака Теперь перейдем к перемещению предметов из рюкзака в слоты героя. Расширим процедуру ShowHeroItems по схеме, аналогичной ShowHeroSlots, добавив в нее обработчик нажатий на клавиши:
procedure ShowHeroItems;
while true do
end;
ShowGame; Что надо делать при выборе пользователем определенного элемента рюкзака? Необходимо проверить, как и в случае с ShowHeroSlots, не пустой ли это элемент, а также выяснить, имеются ли подходящие для предмета и свободные слоты. Последнюю задачу будет решать функция GetFreeSlot, параметром которой выступит предмет. Функция определит, есть ли у героя подходящий слот, проверив заодно допустимость перемещения - ведь меч нельзя надеть на голову, а броню использовать как оружие. Разместим функцию в модуле Hero:
function GetFreeSlot( var H: THero; Itm: TGameItem ): Integer; В ней происходит перебор слотов персонажа, и при нахождении свободного слота (свойство IType имеет значение, отличное от itemNone) выполняется дополнительная проверка - допустимо ли поместить данный предмет в слот с индексом i (эти индексы мы обозначили константами с префиксом "slot"; так, слот тела имеет значение индекса slotBody, равное единице). Такую проверку в соответствии с принципами проектирования "сверху-вниз" вынесем в новую фуанкцию GoodSlot, размещенную в этом же модуле:
function GoodSlot(Slot: Integer; Itm: TGameItem): Boolean;
slotBody : GoodSlot := Itm.IType in [itemArmor];
slotHands: GoodSlot := Itm.IType in [itemHandWeapon];
end; Для каждого значения переменной Slot проверим, подходит ли тип предмета назначению данного слота. На тело героя (slotBody) можно одевать предметы типа "броня" (itemArmor), в руки (slotHands) можно брать ручное оружие (itemHandWeapon). Значения itemArmor и itemHandWeapon вынесены в константы-множества, чтобы данные проверки можно было легко расширять и дополнять. Например, если мы добавим дальнобойное оружие, то соответствующая проверка перепишется так:
slotHands: GoodSlot := Itm.IType in [itemHandWeapon, При добавлении предметов-плащей (накидок на тело) изменится другая проверка:
slotBody : GoodSlot := Itm.IType in [itemArmor, itemCloack]; И так далее. Теперь определим, что будет делать программа, когда человек выбрал в рюкзаке предмет для одевания. Этот предмет надо скопировать из массива Items в массив Slots, удалив затем его из рюкзака.
procedure ShowHeroItems;
while true do
s := GetFreeSlot(Heroes[CurHero],Heroes[CurHero].Items[n]);
ShowGame; Вы можете попрактиковаться в перемещении предметов между рюкзаком и слотами героя. Процедуры ShowHeroItems/ShowHeroSlots вводят команды пользователя с помощью стандартного оператора Паскаля ReadLn. При этом введенное в локальную переменную n значение не проверяется как на логическую корректность (оно должно укладываться в допустимые диапазоны массивов Slots/Items), так и на синтаксическую правильность. Если вместо числа мы попробуем ввести строку типа "абв", программа аварийно завершится со стандартной ошибкой 106 системы Turbo Pascal (Invalid numeric format, неверный формат числа). Поэтому читателю предлагается самостоятельно укрепить этот слабый участок программы. Можно, например, реализовать собственный миниатюрный текстовый редактор, отслеживающий нажатия клавиш, отображающий их на экране и допускающий простейшие исправления. Бросаем предметы Наконец, последней среди задач обработки предметов персонажем станет возможность поднятия предметов с земли и выбрасывание их на землю. Допустим, выбросить предмет из рюкзака, находясь в рабочем экране процедуры ShowHeroItems. Позволять выбрасывать надетые предметы из слотов персонажа мы не будем. Ведь для этого можно предварительно переместить ненужный предмет в рюкзак. В коммерческих играх нередко позволяется перемещать предметы на землю не из рюкзака, а как раз из слотов - например, из рук. При желании вы можете реализовать такую возможность в программе самостоятельно. Но как нам определить, что хочет пользователь - переместить предмет из рюкзака в слот, или наоборот, положить его на землю? Разделим эти два действия, позволив вводить в качестве номера элемента рюкзака как положительные, так и отрицательные значения. Положительное значение, как и раньше, будет означать выбранный номер элемента рюкзака для перемещения в слот, а вот отрицательный (точнее, его модуль, абсолютное значение) - номер предмета в рюкзаке для выкладывания его на землю.
procedure ShowHeroItems;
while true do
if n > 0 then
begin
ShowGame; Если введенное значение положительно, выполняются ранее запрограммированные действия. Если оно отрицательно, значит, нам надо переместить выбранные предмет на землю, то есть убрать его из рюкзака и добавить в глобальный массив Items из модуля GameItem, откорректировав при этом координаты предмета (поля x и y). Отрисовка положенного на землю предмета на карте выполнится автоматически в процедуре ShowGame (точнее, в процедуре ShowItems, вызываемой из нее). Определение свободного места в массиве расположенных на карте предметов происходит в функции GetFreeItemNum. Ее в соответствии с предназначением надо реализовать в модуле GameItem:
function GetFreeItemNum: Integer; Здесь происходит перебор элементов массива Items, и как только находится незанятый элемент, работа функции заканчивается. Отметим, что эта функция может иногда возвращать нулевое значение (свободного места нет из-за ограничений на оперативную память программы), хотя логика игры полагает, что в данном месте локации вполне можно оставить предмет на земле. Очевидного выхода из такой ситуации нет. Можно только порекомендовать создавать массив Items с достаточно солидным запасом, что возможно при реализации игры в среде Windows. При перемещении предмета на карту возможны игровые конфликты, связанные с тем, что на один и тот же тайл карты кладется несколько предметов, и при последующих попытках взять предмет с карты возникнет неоднозначность (непонятно, какой именно предмет брать). Обычно в играх запрещается класть на один тайл сразу много предметов. Вы можете самостоятельно внести в программу подобное улучшение. Теперь перейдем к процедуре взятия предмета с карты. Допустим, персонаж находится на некотором тайле карты, который был подсвечен, как содержащий предмет (символ +). Такая процедура - назовем ее GetItemFromMap, будет вызываться при нажатии на клавишу g (главная процедура программы в модуле Main):
...
' g ' : GetItemFromMap; Вот как запишется ее реализация (модуль Hero):
procedure GetItemFromMap; Прежде всего мы проверяем, есть ли у героя в рюкзаке свободное место (функция GetFreeBag). Если его нет, то работа процедуры заканчивается. Если оно есть, пробегаем по всем элементам массива Items (предметы, размещенные на карте), и как только находится элемент, координаты которого совпадают с координатами героя, выполняется копирование этого предмета в массив Items персонажа (в рюкзак), а элемент глобального массива Items помечается как "пустой". Вы можете протестировать игру, перемещая предметы между слотами и рюкзаком, а также между рюкзаком и картой - в обе стороны. При этом может выявиться следующие недочеты: во-первых, в моменты подъема предметов с земли играющий не получает никакой информации о том, изменилось ли что-то в игровом пространстве. Во-вторых, после того, как персонаж положил предмет на землю, а потом поднял его в том же месте, и отошел в сторону, оказывается, что на карте в этом месте возникает пустое место - вместо тайла карты выводится пробел. Первое недоразумение устраним так. Добавим в процедуру GetItemFromMap информационное сообщение, извещающее человека о том, что с земли поднят некий предмет. Константа STR_GETITEM может быть описана в модуле Texts так:
const STR_GETITEM = ' Вы подобрали ' ; Второе недоразумение решается не менее просто. Достаточно добавить оператор обнуления поля x освобождаемого элемента массива Items:
procedure GetItemFromMap; Итак, мы запрограммировали фактически все необходимые возможности управления нашим героем. Остается только реализовать алгоритмы сражения с монстрами, и отладить уровни игры. Исходный код текущей версии (всегда проверен и работоспособен, главный файл- main.pas): http://russianenterprisesolutions.com/sbo/download/8115.zip 7900 байтов Далее: Готовимся к схватке. (c) 2004-2005 Сергей Бобровский bobrovsky@russianenterprisesolutions.com
Школа программирования с нуля
Дизайн рассылки: Алексей Голубев - Web-дизайн и web-программирование |
Subscribe.Ru
Поддержка подписчиков Другие рассылки этой тематики Другие рассылки этого автора |
Подписан адрес:
Код этой рассылки: comp.soft.prog.prognull.game Архив рассылки |
Отписаться
Вспомнить пароль |
В избранное | ||