Меню сайта
Форма входа
Категории раздела
Уроки по созданию игр [38]
Программирование игр разной сложности
Игровые алгоритмы [24]
Алгоритмы, которые уже реализованы для разных жанров игр
Графика [5]
Учимся работать с графикой в Делфи
Мультимедиа [3]
Работа с мультимедийными возможностями Делфи
Другие статьи [18]
Статьи не вошедшие не в один из разделов
Ошибки [4]
Всевозможные ошибки и пути их решения
Четверг, 03.07.2025, 08:38
Приветствую Вас Гость

Статьи по программированию

Главная » Статьи » Уроки по созданию игр

Создание Ролевой игры РПГ на Паскале и Делфи. Урок 5

Урок 5. Добавляем средства визуализации карты

 

а) Надо различать создание игры и создание движка для игры. Последнее я считаю глупым занятием, если только его авторы не собираются потом движок продавать (хотя все равно конкурировать с коллективами десятков математиков сложно, да и продать хоть что-то НА ПОРЯДОК СЛОЖНЕЕ, чем запрограммировать самый уникальный движок), или же у них нету собственных денег на лицензирование коммерческих движков. Хотя и опен-сорсных движков приличного качества достаточно.

б) Движок для ЗО-игры реального времени и движок пошаговой Цивилизации – вещи очевидно разные. Для Цивилизации можно хоть на Бейсике писать, все равно будет шустрый smile Л хороший 3D и на Си трудно, нужна куча ассемблерных вставок.

Мы не будем делать ЗD-движок реального времени, поэтому возможностей Delphi хватит с избытком.

в) На каком языке написана библиотека и из какой программы она вызывается, значения не имеет потому что все вызовы (интерфейс библиотеки) выполнены в едином стандарте, и функция без разницы, из Си или Паскаля они вызываются. Они даже и не знают об этом. На  скорость работы библиотечных функций, очевидно, форма их вызова никак не сказывается smile (если не принимать в расчет каких-нибудь долей процента из-за разных способов передачи параметров).

г) Вообще неправильно исходить из низкоуровневого быстродействия. Всю графическую работу сегодня берут на себя готовые библиотеки, а программная логика конкретной создаваемой игры отличается тем, что можно потратить месяц работы на вылизывание кода, ИЛИ перевод его с Паскаля на Си, получив 5% выигрыша, а можно потратить неделю на то, чтобы ПОДУМАТЬ как следует и изменить сам АЛГОРИТМ работы прикладной программы так, что выигрыш составит 50% или 500%.

Добавляем средства визуализации карты

Продолжаем это: Программируем карту

…В данной процедуре оказался не реализованным такой момент, как способ перемещения между пещерами. Мы договорились, что для этого будут задействованы специальные тайлы-ступеньки, однако таких входов-выходов должно быть немного. Мастера игростроения рекомендуют в качестве оптимального варианта размещать на карте два спуска вниз и один подъем. Последуем этому совету, добавив в конец процедуры следующий код (и описав дополнительную локальную переменную i):

 

if MapLevel   <  MaxDungeonLevel   then

for  i   :=   1   to  2  do

begin

FreeMapPoint(x,y);

  GameMap[CurMap].Cells[x,y].Tile   :=  tileStairsDown;

end;

 

  if MapLevel   >   1   then

  begin

  FreeMapPoint(x,y);

  GameMap[CurMap].Cells[x,y].Tile   :=  tileStairsUp;

  end;

 

Отметим, что упомянутая, но пока не реализованная процедура FreeMapPoint поиска :иободной точки на карте будет нужна нам и в других точках программы - например, в кжеке подходящего места для предметов, ловушек и т. п. Поэтому вынесем такой алгоритм i отдельную процедуру" FreeMapPoint и поместим ее в модуль Map:

 

procedure   FreeMapPoint(   var  x,y:   Integer   );

begin

repeat

x   :=randora(MAP_WIDTH-LOCAL_MAP_WIDTH*2)+LOCAL_MAP_WIDTH;

у   :=   random(MAP_HEIGHT   -   LOCAL_MAP_HEIGHT*2)    +LOCAL_MAP_HEIGHT;

until  

FreeTile(GameMap[CurMap] .Cells [x,y] .Tile);

end;

 

Здесь мы учли заполненные непроходимыми тайлами сдвиги LOCAL_MAP_WIDTH и LOCAL_MAP_HEIGHT по краям карты.

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

 

program LearningRPG;

uses  Map;

begin

Randomize;

end.

 

Теперь все готово для вывода карты на экран. Для этою добавим в модуль Map процедуру отрисовки всей видимой части. Она будет очень простой - для каждой видимой ячейки карты вызывается процедура ее вывода.

 

procedure  ShowMap;

var  x,y:   Integer;

begin

PrepareMap;

for  x   :=  GameMap[CurMap].LocalMapLeft   to

GameMap[CurMap].LocalMapLeft  +   LOCAL_MAP_WIDTH   -   1   do

for  у   :=  GameMap[CurMap].LocalMapTop   to

GameMap[CurMap].LocalMapTop  +   LOCAL_MAP_HEIGHT  -   1   do ShowCell(GameMap[CurMap].Cells[x,y],x,y);

end;

 

Дополнительная процедура ShowCell добавлена умышленно, так как в игре нам наверняка понадобится возможность выводить (перерисовывать) отдельные элементы карты. Эта процедура будет относиться к "низкоуровневым" возможностям программы, зависящим от конкретной реализации и операционной системы. Где разместить ShowCell? Давайте подготовим новый модуль LowLevel, в котором будем хранить весь наш код, зависящий от реализации.

Процедура PrepareMap требуется нам для того, чтобы учесть особенности реализации графических функций перерисовки экрана. Так, в ДОС-е нам понадобится предварительно очищать экран от старой информации, накопленной на предыдущем игровом такте. Каким образом разделять код, который будет относиться к ДОС-у и к Windows? Правильнее всего это сделать с помощью команд условной компиляции. Сформируем в каталоге проекта файл Defines.Inc. в котором поместим следующие строки:

 

{$DEFINE   DOS_GAME}

{    $DEFINE  WIN_GAME}

{$DEFINE   RUSDOS_GAME}

{    $DEFINE   RUSWIN_GAME)

 

Первые две строчки определяют платформу, для которой собирается проект, вторые две строчки задают, какой язык будет использоваться в программе для вывода всевозможных сообщений. Дело в том, что русские кодировки для ДОС-а и Windows различаются, поэтому нам придется дублировать все сообщения в двух кодировках (Alternative/IBM и Win 1251). Данная возможность также будет крайне полезна при переносе нашей программы на другие языки - например, английский.

Обратите внимание, где поставлен пробел в инструкциях компилятору перед символом $. Если $ следует не сразу за фигурной скобкой, то он уже не воспринимается как инструкция, таким образом "включены" DOSGAME и RUSDOSGAME и "выключены" определения преироцессорных констант, подготовленных для Windows.

Добавим ссылку на файл определений в начало модуля LowLevel, и выделим в нем часть, связанную с ДОС-ом:

 

{$1   DEFINES.INC)

unit LowLevel;

interface

procedure ShowCell(t: TMapCell; x,y: Integer);

implementation

{$IFDEF DOS_GAME}

procedure  ShowCell(t:   TMapCell;   x,y:   Integer);

begin

end;

{ENDIF}

End.

 

Ссылку на модуль Map надо ввести в интерфйсном разделе: interface uses Map;

Размещение ссылок на рабочие модули программы в интерфейсном разделе потенциально чревато неприятными ошибками, связанными с закольцованными ссылками. Например, если мы в дальнейшем определим в интерфейсе модуля LowLevel некий тип или константу, которые захотим использовать в интерфейсной части модуля Map, то получим запрещенную ситуацию - два интерфейсных раздела разных модулей ссылаются друг на друга:

 

unit LowLevel;

interface uses Map;

unit Map;

interface  uses   LowLevel;

 

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

Наш случай - исключение. Модуль LowLevel предназначен только для реализации ни многоуровневых функций вывода на информации экран, зависящих от операционной системы, и поэтому на него достаточно ссылаться из "внутренности" всех других модулей раздела Implementation.

Таким же образом добавим процедуру РгераrеМар. Она будет состоять из одного вызова стандартной функции очистки окна:

 

procedure   РгераrеМар;

begin

СlrScr;

end;

 

Теперь укажем в заголовке реализации модуля Map ссылку на этот модуль: implementation uses LowLevel;

В главной части программы теперь можно вызвать процедуру генерации карты (первого ровня пещеры) и вывода ее на экран. По завершении вывода подождем нажатия на клавишу Enter:

 

program LearningRPG;

uses  Map;

begin

Randomize;

MapGeneration (1) ;

ShowMap;

readln;

end.

 

Прокомпилируем и запустим программу. Пока она, конечно, ничего не покажет, так как процудура ShowCell не содержит никакого кода, но тем не менее генерация карты должна выполняться успешно.

Далее завершаем визуализацию карты и начинаем программировать главного героя.

Категория: Уроки по созданию игр | Добавил: Armageddets (24.11.2012)
Просмотров: 3163 | Теги: программирование игр, как написать игру, карта, урок по созданию игр, ролевая игра | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Наш опрос
Где Вам удобнее оставлять коментарии и задавать вопроссы?
Всего ответов: 24
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0